From: Richard Smith Date: Thu, 1 Feb 2018 20:01:49 +0000 (+0000) Subject: PR36157: When injecting an implicit function declaration in C89, find the right X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f61575826a1eef7d0c0198d6f444894ec72ea394;p=clang PR36157: When injecting an implicit function declaration in C89, find the right DeclContext rather than injecting it wherever we happen to be. This avoids creating functions whose DeclContext is a struct or similar. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@323998 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 1a7d9a8430..526f6802c3 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -12910,10 +12910,20 @@ void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D, /// call, forming a call to an implicitly defined function (per C99 6.5.1p2). NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, Scope *S) { + // Find the scope in which the identifier is injected and the corresponding + // DeclContext. + // FIXME: C89 does not say what happens if there is no enclosing block scope. + // In that case, we inject the declaration into the translation unit scope + // instead. Scope *BlockScope = S; while (!BlockScope->isCompoundStmtScope() && BlockScope->getParent()) BlockScope = BlockScope->getParent(); + Scope *ContextScope = BlockScope; + while (!ContextScope->getEntity()) + ContextScope = ContextScope->getParent(); + ContextRAII SavedContext(*this, ContextScope->getEntity()); + // Before we produce a declaration for an implicitly defined // function, see whether there was a locally-scoped declaration of // this name as a function or variable. If so, use that diff --git a/test/Sema/bitfield.c b/test/Sema/bitfield.c index d625366e4e..13e9480a37 100644 --- a/test/Sema/bitfield.c +++ b/test/Sema/bitfield.c @@ -82,3 +82,7 @@ typedef __typeof__(+(t5.n--)) Unsigned; // also act like compound-assignment. struct Test6 { : 0.0; // expected-error{{type name requires a specifier or qualifier}} }; + +struct PR36157 { + int n : 1 ? 1 : implicitly_declare_function(); // expected-warning {{invalid in C99}} +}; diff --git a/test/Sema/cxx-as-c.c b/test/Sema/cxx-as-c.c new file mode 100644 index 0000000000..41d7350d1f --- /dev/null +++ b/test/Sema/cxx-as-c.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 %s -verify + +// PR36157 +struct Foo { + Foo(int n) : n_(n) {} // expected-error 1+{{}} expected-warning 1+{{}} +private: + int n; +}; +int main() { Foo f; } // expected-error 1+{{}}