llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
26.76k stars 10.96k forks source link

clang: accept-invalid ill-formed C program / assertion `getLangOpts().CPlusPlus && "Call sites of this function should be guarded by checking for C++"' #48607

Open llvmbot opened 3 years ago

llvmbot commented 3 years ago
Bugzilla Link 49263
Version trunk
OS Linux
Reporter LLVM Bugzilla Contributor
CC @zygoloid

Extended Description

Clang accepts this presumably-invalid code, which GCC rejects. It affects 11.0, 12.0, and trunk.

clang: https://godbolt.org/z/b7oaxq
GCC: https://godbolt.org/z/1194qP


$ cat test.c

struct another_struct {
    int my_int;
};

struct my_struct {
    struct {
        int volatile (*func_ptr)(int[] = <, struct another_struct);
    };
};

int volatile func(int a[]) { return a[0]; }

int main() {
    struct my_struct x = { .func_ptr = &func };
    int y = 1;

    return (*x.func_ptr)(&y);
}

$ ./clang -o /tmp/a.out -x c -std=c11 -pedantic -Wall test.c

no any warning or error


I try to make the compilation as strict as possible, so I set "-std=c11 -pedantic -Wall". Actually, the standard does not matter.

llvmbot commented 3 years ago

When we turn assertions on, we can get:

$ ./clang -o /tmp/a.out -x c -std=c11 -pedantic -Wall test.c clang-13: /home/xxx/data/git/llvm-project/clang/lib/Parse/Parser.cpp:2068: bool clang::Parser::TryAnnotateCXXScopeToken(bool): Assertion `getLangOpts().CPlusPlus && "Call sites of this function should be guarded by checking for C++"' failed. PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace, preprocessed source, and associated run script. Stack dump:

  1. Program arguments: /data/xxx/git/llvm-project/build_trunk/bin/clang-13 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all --mrelax-relocations -disable-free -main-file-name test.c -mrelocation-model static -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /data/xxx/git/llvm-project/build_trunk/lib/clang/13.0.0 -internal-isystem /usr/local/include -internal-isystem /data/xxx/git/llvm-project/build_trunk/lib/clang/13.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wall -pedantic -std=c11 -fdebug-compilation-dir=/data/xxx/docker_share/clang -ferror-limit 19 -fgnuc-version=4.2.1 -fcolor-diagnostics -faddrsig -o /tmp/test-2f1b7b.o -x c test.c
  2. test.c:7:52: current parser token 'another_struct'
  3. test.c:5:1: parsing struct/union body 'my_struct'
  4. test.c:6:5: parsing struct/union body 'my_struct::(anonymous)'

    ​0 0x0000000000dfd0a1 __interceptor_backtrace.part.117 asan_interceptors.cc.o:0:0

    ​1 0x000000000d7fb43a llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /home/xxx/data/git/llvm-project/llvm/lib/Support/Unix/Signals.inc:561:7

    ​2 0x000000000d7f1bc1 llvm::sys::RunSignalHandlers() /home/xxx/data/git/llvm-project/llvm/lib/Support/Signals.cpp:72:18

    ​3 0x000000000d7fc5b7 SignalHandler(int) /home/xxx/data/git/llvm-project/llvm/lib/Support/Unix/Signals.inc:407:1

    ​4 0x00007f5f721d88a0 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x128a0)

    ​5 0x00007f5f71bfbf47 raise /build/glibc-2ORdQG/glibc-2.27/signal/../sysdeps/unix/sysv/linux/raise.c:51:0

    ​6 0x00007f5f71bfd8b1 abort /build/glibc-2ORdQG/glibc-2.27/stdlib/abort.c:81:0

    ​7 0x00007f5f71bed42a __assert_fail_base /build/glibc-2ORdQG/glibc-2.27/assert/assert.c:89:0

    ​8 0x00007f5f71bed4a2 (/lib/x86_64-linux-gnu/libc.so.6+0x304a2)

    ​9 0x0000000018337bd9 clang::Parser::TryAnnotateCXXScopeToken(bool) /home/xxx/data/git/llvm-project/clang/lib/Parse/Parser.cpp:0:3

    ​10 0x00000000186bb949 clang::Parser::TryAnnotateOptionalCXXScopeToken(bool) /home/xxx/data/git/llvm-project/clang/include/clang/Parse/Parser.h:850:38

    ​11 0x00000000186bb949 clang::Parser::TryConsumeDeclarationSpecifier() /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseTentative.cpp:192:0

    ​12 0x00000000186c8fd2 clang::Parser::TryParseParameterDeclarationClause(bool*, bool) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseTentative.cpp:1929:11

    ​13 0x000000001835baed clang::Parser::ConsumeAndStoreInitializer(llvm::SmallVector<clang::Token, 4u>&, clang::Parser::CachedInitKind) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseCXXInlineMethods.cpp:0:20

    ​14 0x00000000183ee03d clang::Parser::ParseParameterDeclarationClause(clang::DeclaratorContext, clang::ParsedAttributes&, llvm::SmallVectorImpl&, clang::SourceLocation&) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseDecl.cpp:6882:16

    ​15 0x00000000183e3f3e clang::Parser::ParseFunctionDeclarator(clang::Declarator&, clang::ParsedAttributes&, clang::BalancedDelimiterTracker&, bool, bool) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseDecl.cpp:6496:16

    ​16 0x00000000183da91a clang::Parser::ParseDirectDeclarator(clang::Declarator&) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseDecl.cpp:6172:11

    ​17 0x00000000183d29c7 clang::Parser::ParseDeclaratorInternal(clang::Declarator&, void (clang::Parser::*)(clang::Declarator&)) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseDecl.cpp:5727:7

    ​18 0x00000000183c4d5b clang::ColonProtectionRAIIObject::~ColonProtectionRAIIObject() /home/xxx/data/git/llvm-project/clang/include/clang/Parse/RAIIObjectsForParser.h:0:0

    ​19 0x00000000183c4d5b clang::Parser::ParseStructDeclaration(clang::ParsingDeclSpec&, llvm::function_ref<void (clang::ParsingFieldDeclarator&)>) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseDecl.cpp:4172:0

    ​20 0x00000000183c7322 clang::ParsingDeclSpec::~ParsingDeclSpec() /home/xxx/data/git/llvm-project/clang/include/clang/Parse/RAIIObjectsForParser.h:0:0

    ​21 0x00000000183c7322 clang::Parser::ParseStructUnionBody(clang::SourceLocation, clang::TypeSpecifierType, clang::RecordDecl*) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseDecl.cpp:4278:0

    ​22 0x000000001842e535 clang::Parser::ParseClassSpecifier(clang::tok::TokenKind, clang::SourceLocation, clang::DeclSpec&, clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, bool, clang::Parser::DeclSpecContext, clang::Parser::ParsedAttributesWithRange&) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp:1972:20

    ​23 0x0000000018394f87 clang::Parser::ParseDeclarationSpecifiers(clang::DeclSpec&, clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, clang::Parser::DeclSpecContext, clang::Parser::LateParsedAttrList*) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseDecl.cpp:3929:7

    ​24 0x0000000018371507 clang::Parser::ParseSpecifierQualifierList(clang::DeclSpec&, clang::AccessSpecifier, clang::Parser::DeclSpecContext) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseDecl.cpp:2444:3

    ​25 0x00000000183c438c clang::Token::is(clang::tok::TokenKind) const /home/xxx/data/git/llvm-project/clang/include/clang/Lex/Token.h:0:0

    ​26 0x00000000183c438c clang::Parser::ParseStructDeclaration(clang::ParsingDeclSpec&, llvm::function_ref<void (clang::ParsingFieldDeclarator&)>) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseDecl.cpp:4141:0

    ​27 0x00000000183c7322 clang::ParsingDeclSpec::~ParsingDeclSpec() /home/xxx/data/git/llvm-project/clang/include/clang/Parse/RAIIObjectsForParser.h:0:0

    ​28 0x00000000183c7322 clang::Parser::ParseStructUnionBody(clang::SourceLocation, clang::TypeSpecifierType, clang::RecordDecl*) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseDecl.cpp:4278:0

    ​29 0x000000001842e535 clang::Parser::ParseClassSpecifier(clang::tok::TokenKind, clang::SourceLocation, clang::DeclSpec&, clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, bool, clang::Parser::DeclSpecContext, clang::Parser::ParsedAttributesWithRange&) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp:1972:20

    ​30 0x0000000018394f87 clang::Parser::ParseDeclarationSpecifiers(clang::DeclSpec&, clang::Parser::ParsedTemplateInfo const&, clang::AccessSpecifier, clang::Parser::DeclSpecContext, clang::Parser::LateParsedAttrList*) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseDecl.cpp:3929:7

    ​31 0x0000000018323b6d clang::Parser::ParseDeclOrFunctionDefInternal(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec&, clang::AccessSpecifier) /home/xxx/data/git/llvm-project/clang/lib/Parse/Parser.cpp:1040:3

    ​32 0x0000000018322237 clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*, clang::AccessSpecifier) /home/xxx/data/git/llvm-project/clang/lib/Parse/Parser.cpp:1150:12

    ​33 0x000000001831f00d clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*) /home/xxx/data/git/llvm-project/clang/lib/Parse/Parser.cpp:0:12

    ​34 0x0000000018317f4e clang::Parser::ParseTopLevelDecl(clang::OpaquePtr&, bool) /home/xxx/data/git/llvm-project/clang/lib/Parse/Parser.cpp:716:10

    ​35 0x00000000183047f9 clang::ParseAST(clang::Sema&, bool, bool) /home/xxx/data/git/llvm-project/clang/lib/Parse/ParseAST.cpp:157:15

    ​36 0x00000000105c90c3 clang::ASTFrontendAction::ExecuteAction() /home/xxx/data/git/llvm-project/clang/lib/Frontend/FrontendAction.cpp:1058:1

    ​37 0x0000000012cff7d9 clang::CodeGenAction::ExecuteAction() /home/xxx/data/git/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp:1082:30

    ​38 0x00000000105c5efd clang::FrontendAction::Execute() /home/xxx/data/git/llvm-project/clang/lib/Frontend/FrontendAction.cpp:0:8

    ​39 0x0000000010394e0a llvm::Error::operator bool() /home/xxx/data/git/llvm-project/llvm/include/llvm/Support/Error.h:0:0

    ​40 0x0000000010394e0a clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /home/xxx/data/git/llvm-project/clang/lib/Frontend/CompilerInstance.cpp:949:0

    ​41 0x0000000010ac5a2e clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /home/xxx/data/git/llvm-project/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:278:25

    ​42 0x0000000000e9b85d cc1_main(llvm::ArrayRef<char const>, char const, void*) /home/xxx/data/git/llvm-project/clang/tools/driver/cc1_main.cpp:246:15

    ​43 0x0000000000e82e17 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&) /home/xxx/data/git/llvm-project/clang/tools/driver/driver.cpp:330:12

    ​44 0x0000000000e7af13 main /home/xxx/data/git/llvm-project/clang/tools/driver/driver.cpp:407:12

    ​45 0x00007f5f71bdeb97 __libc_start_main /build/glibc-2ORdQG/glibc-2.27/csu/../csu/libc-start.c:344:0

    ​46 0x0000000000d7aada _start (/data/xxx/git/llvm-project/build_trunk/bin/clang-13+0xd7aada)

    clang-13: error: unable to execute command: Aborted (core dumped) clang-13: error: clang frontend command failed due to signal (use -v to see invocation) clang version 13.0.0 (https://github.com/llvm/llvm-project.git b006902b2dfac792e8ade73798ca1b216654faf7) Target: x86_64-unknown-linux-gnu Thread model: posix InstalledDir: /data/xxx/git/llvm-project/build_trunk/bin clang-13: note: diagnostic msg:


PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT: Preprocessed source(s) and associated run script(s) are located at: clang-13: note: diagnostic msg: /tmp/test-e239b5.c clang-13: note: diagnostic msg: /tmp/test-e239b5.sh clang-13: note: diagnostic msg:


$ cat /tmp/test-e239b5.sh

Crash reproducer for clang version 13.0.0 (https://github.com/llvm/llvm-project.git b006902b2dfac792e8ade73798ca1b216654faf7)

Driver args: "-o" "/tmp/a.out" "-x" "c" "-std=c11" "-pedantic" "-Wall" "test.c"

Original command: "/data/xxx/git/llvm-project/build_trunk/bin/clang-13" "-cc1" "-triple" "x86_64-unknown-linux-gnu" "-emit-obj" "-mrelax-all" "--mrelax-relocations" "-disable-free" "-main-file-name" "test.c" "-mrelocation-model" "static" "-mframe-pointer=all" "-fmath-errno" "-fno-rounding-math" "-mconstructor-aliases" "-munwind-tables" "-target-cpu" "x86-64" "-tune-cpu" "generic" "-fno-split-dwarf-inlining" "-debugger-tuning=gdb" "-resource-dir" "/data/xxx/git/llvm-project/build_trunk/lib/clang/13.0.0" "-internal-isystem" "/usr/local/include" "-internal-isystem" "/data/xxx/git/llvm-project/build_trunk/lib/clang/13.0.0/include" "-internal-externc-isystem" "/usr/include/x86_64-linux-gnu" "-internal-externc-isystem" "/include" "-internal-externc-isystem" "/usr/include" "-Wall" "-pedantic" "-std=c11" "-fdebug-compilation-dir=/data/xxx/docker_share/clang" "-ferror-limit" "19" "-fgnuc-version=4.2.1" "-fcolor-diagnostics" "-faddrsig" "-o" "/tmp/test-2f1b7b.o" "-x" "c" "test.c"

"/data/xxx/git/llvm-project/build_trunk/bin/clang-13" "-cc1" "-triple" "x86_64-unknown-linux-gnu" "-emit-obj" "-mrelax-all" "--mrelax-relocations" "-disable-free" "-main-file-name" "test.c" "-mrelocation-model" "static" "-mframe-pointer=all" "-fmath-errno" "-fno-rounding-math" "-mconstructor-aliases" "-munwind-tables" "-target-cpu" "x86-64" "-tune-cpu" "generic" "-fno-split-dwarf-inlining" "-debugger-tuning=gdb" "-Wall" "-pedantic" "-std=c11" "-fdebug-compilation-dir=/data/xxx/docker_share/clang" "-ferror-limit" "19" "-fgnuc-version=4.2.1" "-fcolor-diagnostics" "-faddrsig" "-x" "c" "test-e239b5.c"

AaronBallman commented 1 year ago

I can no longer reproduce the assertion, but we still fail to reject this invalid code. The test case can be reduced to:

struct huh {
  int (*func_ptr)(int = <);
};
llvmbot commented 1 year ago

@llvm/issue-subscribers-clang-frontend

AaronBallman commented 1 year ago

The issue is that we're relying on late parsing the class to diagnose this, but late parsing of classes doesn't happen in C as it does in C++.

@zygoloid -- I can approach this two different ways: either add support for late parsing of classes in C, or add && getLangOpts().CPlusPlus to https://github.com/llvm/llvm-project/blob/38dfcf96dfd5d88e641e8054ea2f3a008ff8bcfd/clang/lib/Parse/ParseDecl.cpp#L7434 The latter feels like a bit of a hack, but it 1) diagnoses reasonably, and 2) breaks zero tests. The former worries me because of how likely it is that we've baked C++ assumptions into late parsing. You've done more with the late parsing functionality than I have; do you have a feeling for which is the right approach?