def err_language_linkage_spec_not_ascii : Error<
"string literal in language linkage specifier cannot have an "
"encoding-prefix">;
-def warn_use_out_of_scope_declaration : Warning<
- "use of out-of-scope declaration of %0">;
+def ext_use_out_of_scope_declaration : ExtWarn<
+ "use of out-of-scope declaration of %0%select{| whose type is not "
+ "compatible with that of an implicit declaration}1">,
+ InGroup<DiagGroup<"out-of-scope-function">>;
def err_inline_non_function : Error<
"'inline' can only appear on functions%select{| and non-local variables}0">;
def err_noreturn_non_function : Error<
/// 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.
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) {
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;
The list of warnings below should NEVER grow. It should gradually shrink to 0.
-CHECK: Warnings without flags (78):
+CHECK: Warnings without flags (77):
CHECK-NEXT: ext_excess_initializers
CHECK-NEXT: ext_excess_initializers_in_char_array_initializer
CHECK-NEXT: ext_expected_semi_decl_list
CHECK-NEXT: warn_undef_interface
CHECK-NEXT: warn_undef_interface_suggest
CHECK-NEXT: warn_undef_protocolref
-CHECK-NEXT: warn_use_out_of_scope_declaration
CHECK-NEXT: warn_weak_identifier_undeclared
CHECK-NEXT: warn_weak_import
// RUN: %clang_cc1 %s -std=c90 -verify -fsyntax-only
void t0(int x) {
+ int explicit_decl();
int (*p)();
if(x > 0)
- x = g() + 1;
+ x = g() + 1; // expected-note {{previous implicit declaration}}
p = g;
if(x < 0) {
extern void u(int (*)[h()]);
}
p = g; /* expected-error {{use of undeclared identifier 'g'}} */
p = h; /* expected-error {{use of undeclared identifier 'h'}} */
+ explicit_decl();
+ p = explicit_decl;
}
int t2(int x) {
return y;
}
+int PR34822() {
+ {int i = sizeof(PR34822_foo());} /* expected-note {{previous definition is here}} */
+ {extern int PR34822_foo;} /* expected-error {{redefinition of 'PR34822_foo' as different kind of symbol}} */
+
+ {extern int PR34822_bar;} /* expected-note {{previous declaration is here}} */
+ {int i = sizeof(PR34822_bar());} /* expected-warning {{use of out-of-scope declaration of 'PR34822_bar' whose type is not compatible with that of an implicit declaration}} expected-error {{called object type 'int' is not a function or function pointer}} */
+}
+
int (*p)() = g; /* expected-error {{use of undeclared identifier 'g'}} */
int (*q)() = h; /* expected-error {{use of undeclared identifier 'h'}} */
-float g(); /* not expecting conflicting types diagnostics here */
+float g(); /* expected-error {{conflicting types for 'g'}} */
int32_t *vector[16];
const char compDesc[16 + 1];
int32_t compCount = 0;
- if (_CFCalendarDecomposeAbsoluteTimeV(compDesc, vector, compCount)) { // expected-error {{implicit declaration of function '_CFCalendarDecomposeAbsoluteTimeV' is invalid in C99}}
+ if (_CFCalendarDecomposeAbsoluteTimeV(compDesc, vector, compCount)) { // expected-error {{implicit declaration of function '_CFCalendarDecomposeAbsoluteTimeV' is invalid in C99}} expected-note {{previous implicit declaration}}
}
printg("Hello, World!\n"); // expected-error{{implicit declaration of function 'printg' is invalid in C99}} \
__builtin_is_les(1, 3); // expected-error{{use of unknown builtin '__builtin_is_les'}}
}
-Boolean _CFCalendarDecomposeAbsoluteTimeV(const char *componentDesc, int32_t **vector, int32_t count) {
+Boolean _CFCalendarDecomposeAbsoluteTimeV(const char *componentDesc, int32_t **vector, int32_t count) { // expected-error {{conflicting types}}
return 0;
}