summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-10-04 01:49:22 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-10-04 01:49:22 +0000
commit9bfa970a40095db93018a0b16a48e2710dab0d9e (patch)
treee2b5213b22b4a5aff230467f7adb82f2e5e00bca /clang/lib
parent83fd6a1243d2c704332ca7633c2d4ebe02b4a86d (diff)
downloadbcm5719-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.cpp44
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;
OpenPOWER on IntegriCloud