diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-10-04 01:49:22 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-10-04 01:49:22 +0000 |
commit | 9bfa970a40095db93018a0b16a48e2710dab0d9e (patch) | |
tree | e2b5213b22b4a5aff230467f7adb82f2e5e00bca /clang/lib | |
parent | 83fd6a1243d2c704332ca7633c2d4ebe02b4a86d (diff) | |
download | bcm5719-llvm-9bfa970a40095db93018a0b16a48e2710dab0d9e.tar.gz bcm5719-llvm-9bfa970a40095db93018a0b16a48e2710dab0d9e.zip |
PR34822: Fix a collection of related bugs with our handling of C89 implicit function declarations.
We were injecting the function into the wrong semantic context, resulting in it
failing to be registered as a global for redeclaration lookup. As a
consequence, we accepted invalid code since r310616.
Fixing that resulted in the "out-of-scope declaration" diagnostic firing a lot
more often. It turned out that warning codepath was non-conforming, because it
did not cause us to inject the implicitly-declared function into the enclosing
block scope. We now only warn if the type of the out-of-scope declaration
doesn't match the type of an implicitly-declared function; in all other cases,
we produce the normal warning for an implicitly-declared function.
llvm-svn: 314871
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index fcdc0b39dda..06009b17564 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12613,14 +12613,32 @@ 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) { + Scope *BlockScope = S; + while (!BlockScope->isCompoundStmtScope() && BlockScope->getParent()) + BlockScope = BlockScope->getParent(); + // 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 // (non-visible) declaration, and complain about it. - if (NamedDecl *ExternCPrev = findLocallyScopedExternCDecl(&II)) { - Diag(Loc, diag::warn_use_out_of_scope_declaration) << ExternCPrev; - Diag(ExternCPrev->getLocation(), diag::note_previous_declaration); - return ExternCPrev; + NamedDecl *ExternCPrev = findLocallyScopedExternCDecl(&II); + if (ExternCPrev) { + // We still need to inject the function into the enclosing block scope so + // that later (non-call) uses can see it. + PushOnScopeChains(ExternCPrev, BlockScope, /*AddToContext*/false); + + // C89 footnote 38: + // If in fact it is not defined as having type "function returning int", + // the behavior is undefined. + if (!isa<FunctionDecl>(ExternCPrev) || + !Context.typesAreCompatible( + cast<FunctionDecl>(ExternCPrev)->getType(), + Context.getFunctionNoProtoType(Context.IntTy))) { + Diag(Loc, diag::ext_use_out_of_scope_declaration) + << ExternCPrev << !getLangOpts().C99; + Diag(ExternCPrev->getLocation(), diag::note_previous_declaration); + return ExternCPrev; + } } // Extension in C99. Legal in C90, but warn about it. @@ -12636,6 +12654,12 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, diag_id = diag::warn_implicit_function_decl; Diag(Loc, diag_id) << &II; + // If we found a prior declaration of this function, don't bother building + // another one. We've already pushed that one into scope, so there's nothing + // more to do. + if (ExternCPrev) + return ExternCPrev; + // Because typo correction is expensive, only do it if the implicit // function declaration is going to be treated as an error. if (Diags.getDiagnosticLevel(diag_id, Loc) >= DiagnosticsEngine::Error) { @@ -12687,19 +12711,9 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, D.SetIdentifier(&II, Loc); // Insert this function into the enclosing block scope. - while (S && !S->isCompoundStmtScope()) - S = S->getParent(); - if (S == nullptr) - S = TUScope; - - DeclContext *PrevDC = CurContext; - CurContext = Context.getTranslationUnitDecl(); - - FunctionDecl *FD = cast<FunctionDecl>(ActOnDeclarator(S, D)); + FunctionDecl *FD = cast<FunctionDecl>(ActOnDeclarator(BlockScope, D)); FD->setImplicit(); - CurContext = PrevDC; - AddKnownFunctionAttributes(FD); return FD; |