[cfe-commits] r65386 - in /cfe/trunk: include/clang/AST/Decl.h lib/AST/Decl.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaLookup.cpp test/Sema/function-redecl.c test/Sema/var-redecl.c
Douglas Gregor
dgregor at apple.com
Tue Feb 24 12:03:32 PST 2009
Author: dgregor
Date: Tue Feb 24 14:03:32 2009
New Revision: 65386
URL: http://llvm.org/viewvc/llvm-project?rev=65386&view=rev
Log:
When we're declaring an object or function with linkage, teach name
lookup to skip over names without linkage. This finishes
<rdar://problem/6127293>.
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaLookup.cpp
cfe/trunk/test/Sema/function-redecl.c
cfe/trunk/test/Sema/var-redecl.c
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=65386&r1=65385&r2=65386&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Tue Feb 24 14:03:32 2009
@@ -109,6 +109,9 @@
/// overloaded function.
bool declarationReplaces(NamedDecl *OldD) const;
+ /// \brief Determine whether this declaration has linkage.
+ bool hasLinkage() const;
+
static bool classof(const Decl *D) {
return D->getKind() >= NamedFirst && D->getKind() <= NamedLast;
}
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=65386&r1=65385&r2=65386&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Tue Feb 24 14:03:32 2009
@@ -205,6 +205,15 @@
return this->getKind() == OldD->getKind();
}
+bool NamedDecl::hasLinkage() const {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(this))
+ return VD->hasExternalStorage() || VD->isFileVarDecl();
+
+ if (isa<FunctionDecl>(this) && !isa<CXXMethodDecl>(this))
+ return true;
+
+ return false;
+}
//===----------------------------------------------------------------------===//
// VarDecl Implementation
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=65386&r1=65385&r2=65386&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Feb 24 14:03:32 2009
@@ -567,7 +567,12 @@
/// Look up a namespace name within a C++ using directive or
/// namespace alias definition, ignoring non-namespace names (C++
/// [basic.lookup.udir]p1).
- LookupNamespaceName
+ LookupNamespaceName,
+ // Look up an ordinary name that is going to be redeclared as a
+ // name with linkage. This lookup ignores any declarations that
+ // are outside of the current scope unless they have linkage. See
+ // C99 6.2.2p4-5 and C++ [basic.link]p6.
+ LookupRedeclarationWithLinkage
};
/// @brief Represents the results of name lookup.
@@ -807,12 +812,13 @@
public:
/// Determines whether D is a suitable lookup result according to the
/// lookup criteria.
- static bool isAcceptableLookupResult(Decl *D, LookupNameKind NameKind,
+ static bool isAcceptableLookupResult(NamedDecl *D, LookupNameKind NameKind,
unsigned IDNS) {
switch (NameKind) {
case Sema::LookupOrdinaryName:
case Sema::LookupTagName:
case Sema::LookupMemberName:
+ case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping
return D->isInIdentifierNamespace(IDNS);
case Sema::LookupOperatorName:
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=65386&r1=65385&r2=65386&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Feb 24 14:03:32 2009
@@ -1334,10 +1334,29 @@
NamedDecl *New;
bool InvalidDecl = false;
+ QualType R = GetTypeForDeclarator(D, S);
+ if (R.isNull()) {
+ InvalidDecl = true;
+ R = Context.IntTy;
+ }
+
// See if this is a redefinition of a variable in the same scope.
if (!D.getCXXScopeSpec().isSet() && !D.getCXXScopeSpec().isInvalid()) {
+ LookupNameKind NameKind = LookupOrdinaryName;
+
+ // If the declaration we're planning to build will be a function
+ // or object with linkage, then look for another declaration with
+ // linkage (C99 6.2.2p4-5 and C++ [basic.link]p6).
+ if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
+ /* Do nothing*/;
+ else if (R->isFunctionType()) {
+ if (CurContext->isFunctionOrMethod())
+ NameKind = LookupRedeclarationWithLinkage;
+ } else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern)
+ NameKind = LookupRedeclarationWithLinkage;
+
DC = CurContext;
- PrevDecl = LookupName(S, Name, LookupOrdinaryName, true,
+ PrevDecl = LookupName(S, Name, NameKind, true,
D.getDeclSpec().getStorageClassSpec() !=
DeclSpec::SCS_static,
D.getIdentifierLoc());
@@ -1402,17 +1421,11 @@
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef)
PrevDecl = 0;
- QualType R = GetTypeForDeclarator(D, S);
- if (R.isNull()) {
- InvalidDecl = true;
- R = Context.IntTy;
- }
-
bool Redeclaration = false;
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
New = ActOnTypedefDeclarator(S, D, DC, R, LastDeclarator, PrevDecl,
InvalidDecl, Redeclaration);
- } else if (R.getTypePtr()->isFunctionType()) {
+ } else if (R->isFunctionType()) {
New = ActOnFunctionDeclarator(S, D, DC, R, LastDeclarator, PrevDecl,
IsFunctionDefinition, InvalidDecl,
Redeclaration);
@@ -1561,6 +1574,8 @@
// FIXME: PrevDecl could be an OverloadedFunctionDecl, in which
// case we need to check each of the overloaded functions.
+ if (!PrevDecl->hasLinkage())
+ return false;
if (Context.getLangOptions().CPlusPlus) {
// C++ [basic.link]p6:
@@ -1595,13 +1610,6 @@
}
}
- // If the declaration we've found has no linkage, ignore it.
- if (VarDecl *VD = dyn_cast<VarDecl>(PrevDecl)) {
- if (!VD->hasGlobalStorage())
- return false;
- } else if (!isa<FunctionDecl>(PrevDecl))
- return false;
-
return true;
}
@@ -1755,9 +1763,7 @@
// same scope as the new declaration, this may still be an
// acceptable redeclaration.
if (PrevDecl && !isDeclInScope(PrevDecl, DC, S) &&
- !((NewVD->hasExternalStorage() ||
- (NewVD->isFileVarDecl() &&
- NewVD->getStorageClass() != VarDecl::Static)) &&
+ !(NewVD->hasLinkage() &&
isOutOfScopePreviousDeclaration(PrevDecl, DC, Context)))
PrevDecl = 0;
@@ -1788,7 +1794,7 @@
// declaration into translation unit scope so that all external
// declarations are visible.
if (!getLangOptions().CPlusPlus && CurContext->isFunctionOrMethod() &&
- NewVD->hasExternalStorage())
+ NewVD->hasLinkage())
InjectLocallyScopedExternalDeclaration(NewVD);
return NewVD;
@@ -2006,9 +2012,8 @@
// same scope as the new declaration, this may still be an
// acceptable redeclaration.
if (PrevDecl && !isDeclInScope(PrevDecl, DC, S) &&
- (isa<CXXMethodDecl>(NewFD) ||
- NewFD->getStorageClass() == FunctionDecl::Static ||
- !isOutOfScopePreviousDeclaration(PrevDecl, DC, Context)))
+ !(NewFD->hasLinkage() &&
+ isOutOfScopePreviousDeclaration(PrevDecl, DC, Context)))
PrevDecl = 0;
// Merge or overload the declaration with an existing declaration of
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=65386&r1=65385&r2=65386&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Tue Feb 24 14:03:32 2009
@@ -271,6 +271,7 @@
switch (NameKind) {
case Sema::LookupOrdinaryName:
case Sema::LookupOperatorName:
+ case Sema::LookupRedeclarationWithLinkage:
IDNS = Decl::IDNS_Ordinary;
if (CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member;
@@ -763,16 +764,40 @@
case Sema::LookupNamespaceName:
assert(false && "C does not perform these kinds of name lookup");
break;
+
+ case Sema::LookupRedeclarationWithLinkage:
+ // Find the nearest non-transparent declaration scope.
+ while (!(S->getFlags() & Scope::DeclScope) ||
+ (S->getEntity() &&
+ static_cast<DeclContext *>(S->getEntity())
+ ->isTransparentContext()))
+ S = S->getParent();
+ IDNS = Decl::IDNS_Ordinary;
+ break;
}
// Scan up the scope chain looking for a decl that matches this
// identifier that is in the appropriate namespace. This search
// should not take long, as shadowing of names is uncommon, and
// deep shadowing is extremely uncommon.
+ bool LeftStartingScope = false;
+
for (IdentifierResolver::iterator I = IdResolver.begin(Name),
IEnd = IdResolver.end();
I != IEnd; ++I)
if ((*I)->isInIdentifierNamespace(IDNS)) {
+ if (NameKind == LookupRedeclarationWithLinkage) {
+ // Determine whether this (or a previous) declaration is
+ // out-of-scope.
+ if (!LeftStartingScope && !S->isDeclScope(*I))
+ LeftStartingScope = true;
+
+ // If we found something outside of our starting scope that
+ // does not have linkage, skip it.
+ if (LeftStartingScope && !((*I)->hasLinkage()))
+ continue;
+ }
+
if ((*I)->getAttr<OverloadableAttr>()) {
// If this declaration has the "overloadable" attribute, we
// might have a set of overloaded functions.
@@ -806,7 +831,8 @@
// If we didn't find a use of this identifier, and if the identifier
// corresponds to a compiler builtin, create the decl object for the builtin
// now, injecting it into translation unit scope, and return it.
- if (NameKind == LookupOrdinaryName) {
+ if (NameKind == LookupOrdinaryName ||
+ NameKind == LookupRedeclarationWithLinkage) {
IdentifierInfo *II = Name.getAsIdentifierInfo();
if (II && AllowBuiltinCreation) {
// If this is a builtin on this (or all) targets, create the decl.
Modified: cfe/trunk/test/Sema/function-redecl.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/function-redecl.c?rev=65386&r1=65385&r2=65386&view=diff
==============================================================================
--- cfe/trunk/test/Sema/function-redecl.c (original)
+++ cfe/trunk/test/Sema/function-redecl.c Tue Feb 24 14:03:32 2009
@@ -46,7 +46,7 @@
static void g3(int x) { } // expected-error{{static declaration of 'g3' follows non-static declaration}}
void test2() {
- extern int f2; // expected-note{{previous definition is here}}
+ extern int f2; // expected-note 2 {{previous definition is here}}
{
void f2(int); // expected-error{{redefinition of 'f2' as different kind of symbol}}
}
@@ -54,7 +54,7 @@
{
int f2;
{
- void f2(int); // okay
+ void f2(int); // expected-error{{redefinition of 'f2' as different kind of symbol}}
}
}
}
Modified: cfe/trunk/test/Sema/var-redecl.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/var-redecl.c?rev=65386&r1=65385&r2=65386&view=diff
==============================================================================
--- cfe/trunk/test/Sema/var-redecl.c (original)
+++ cfe/trunk/test/Sema/var-redecl.c Tue Feb 24 14:03:32 2009
@@ -28,3 +28,24 @@
float outer5; // expected-error{{redefinition of 'outer5' with a different type}}
int outer8(int); // expected-error{{redefinition of 'outer8' as different kind of symbol}}
float outer9; // expected-error{{redefinition of 'outer9' with a different type}}
+
+extern int outer13; // expected-note{{previous definition is here}}
+void outer_shadowing_test() {
+ extern int outer10;
+ extern int outer11; // expected-note{{previous definition is here}}
+ extern int outer12; // expected-note{{previous definition is here}}
+ {
+ float outer10;
+ float outer11;
+ float outer12;
+ {
+ extern int outer10; // okay
+ extern float outer11; // expected-error{{redefinition of 'outer11' with a different type}}
+ static double outer12;
+ {
+ extern float outer12; // expected-error{{redefinition of 'outer12' with a different type}}
+ extern float outer13; // expected-error{{redefinition of 'outer13' with a different type}}
+ }
+ }
+ }
+}
More information about the cfe-commits
mailing list