"declarator requires an identifier")
DIAG(err_bad_language, ERROR,
"unknown linkage language")
+DIAG(warn_use_out_of_scope_declaration, WARNING,
+ "use of out-of-scope declaration of %0")
/// Built-in functions.
DIAG(ext_implicit_lib_function_decl, EXTWARN,
InvalidDecl = true;
}
}
+
+ if (!getLangOptions().CPlusPlus && CurContext->isFunctionOrMethod()) {
+ // If this is a function declaration in local scope, inject its
+ // name into the top-level scope so that it will be visible to
+ // later uses and declarations of the same function, since the
+ // function is external.
+ // FIXME: We don't do this in C++ because, although we would like
+ // to get the extra checking that this operation implies,
+ // the declaration itself is not visible according to C++'s rules.
+ IdentifierResolver::iterator I = IdResolver.begin(Name),
+ IEnd = IdResolver.end();
+ NamedDecl *PrevIdDecl = 0;
+ while (I != IEnd && !isa<TranslationUnitDecl>((*I)->getDeclContext())) {
+ PrevIdDecl = *I;
+ ++I;
+ }
+
+ if (I == IEnd) {
+ // No name with this identifier has been declared at translation
+ // unit scope. Add this name into the appropriate scope.
+ if (PrevIdDecl)
+ IdResolver.AddShadowedDecl(NewFD, PrevIdDecl);
+ else
+ IdResolver.AddDecl(NewFD);
+ TUScope->AddDecl(NewFD);
+ return NewFD;
+ }
+
+ if (isa<TagDecl>(*I)) {
+ // The first thing we found was a tag declaration, so insert
+ // this function so that it will be found before the tag
+ // declaration.
+ if (PrevIdDecl)
+ IdResolver.AddShadowedDecl(NewFD, PrevIdDecl);
+ else
+ IdResolver.AddDecl(NewFD);
+ TUScope->AddDecl(NewFD);
+ } else if (isa<FunctionDecl>(*I) && NewFD->declarationReplaces(*I)) {
+ // We found a previous declaration of the same function. Replace
+ // that declaration with this one.
+ TUScope->RemoveDecl(*I);
+ TUScope->AddDecl(NewFD);
+ IdResolver.RemoveDecl(*I);
+ if (PrevIdDecl)
+ IdResolver.AddShadowedDecl(NewFD, PrevIdDecl);
+ else
+ IdResolver.AddDecl(NewFD);
+ }
+
+ return NewFD;
+ }
+
return NewFD;
}
}
// See if this is a deleted function.
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isDeleted()) {
Diag(Loc, diag::err_deleted_function_use);
Diag(D->getLocation(), diag::note_unavailable_here) << true;
return true;
}
+ }
// See if the decl is unavailable
if (D->getAttr<UnavailableAttr>()) {
Diag(D->getLocation(), diag::note_unavailable_here) << 0;
}
+ if (D->getDeclContext()->isFunctionOrMethod() &&
+ !D->getDeclContext()->Encloses(CurContext)) {
+ // We've found the name of a function or variable that was
+ // declared with external linkage within another function (and,
+ // therefore, a scope where we wouldn't normally see the
+ // declaration). Once we've made sure that no previous declaration
+ // was properly made visible, produce a warning.
+ bool HasGlobalScopedDeclaration = false;
+ for (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); FD;
+ FD = FD->getPreviousDeclaration()) {
+ if (FD->getDeclContext()->isFileContext()) {
+ HasGlobalScopedDeclaration = true;
+ break;
+ }
+ }
+ // FIXME: do the same thing for variable declarations
+
+ if (!HasGlobalScopedDeclaration) {
+ Diag(Loc, diag::warn_use_out_of_scope_declaration) << D;
+ Diag(D->getLocation(), diag::note_previous_declaration);
+ }
+ }
return false;
}
}
}
}
+
+// <rdar://problem/6127293>
+int outer1(int); // expected-note{{previous declaration is here}}
+struct outer3 { };
+int outer4(int);
+int outer5; // expected-note{{previous definition is here}}
+int *outer7(int);
+
+void outer_test() {
+ int outer1(float); // expected-error{{conflicting types for 'outer1'}}
+ int outer2(int); // expected-note{{previous declaration is here}}
+ int outer3(int); // expected-note{{previous declaration is here}}
+ int outer4(int); // expected-note{{previous declaration is here}}
+ int outer5(int); // expected-error{{redefinition of 'outer5' as different kind of symbol}}
+ int* outer6(int); // expected-note{{previous declaration is here}}
+ int *outer7(int);
+
+ int *ip7 = outer7(6);
+}
+
+int outer2(float); // expected-error{{conflicting types for 'outer2'}}
+int outer3(float); // expected-error{{conflicting types for 'outer3'}}
+int outer4(float); // expected-error{{conflicting types for 'outer4'}}
+
+void outer_test2(int x) {
+ int* ip = outer6(x); // expected-warning{{use of out-of-scope declaration of 'outer6'}}
+ int *ip2 = outer7(x);
+}