forked from OSchip/llvm-project
Revert "C++ doesn't really use "namespaces" for different kinds of names the same", which seems to break most C++ nightly test apps.
llvm-svn: 102174
This commit is contained in:
parent
e97d39b0f2
commit
45b2d8ab42
|
@ -76,63 +76,24 @@ public:
|
||||||
#include "clang/AST/DeclNodes.def"
|
#include "clang/AST/DeclNodes.def"
|
||||||
};
|
};
|
||||||
|
|
||||||
/// IdentifierNamespace - The different namespaces in which
|
/// IdentifierNamespace - According to C99 6.2.3, there are four
|
||||||
/// declarations may appear. According to C99 6.2.3, there are
|
/// namespaces, labels, tags, members and ordinary
|
||||||
/// four namespaces, labels, tags, members and ordinary
|
/// identifiers. These are meant as bitmasks, so that searches in
|
||||||
/// identifiers. C++ describes lookup completely differently:
|
/// C++ can look into the "tag" namespace during ordinary lookup. We
|
||||||
/// certain lookups merely "ignore" certain kinds of declarations,
|
/// use additional namespaces for Objective-C entities. We also put
|
||||||
/// usually based on whether the declaration is of a type, etc.
|
/// C++ friend declarations (of previously-undeclared entities) in
|
||||||
///
|
/// shadow namespaces, and 'using' declarations (as opposed to their
|
||||||
/// These are meant as bitmasks, so that searches in
|
/// implicit shadow declarations) can be found in their own
|
||||||
/// C++ can look into the "tag" namespace during ordinary lookup.
|
/// namespace.
|
||||||
///
|
|
||||||
/// Decl currently provides 16 bits of IDNS bits.
|
|
||||||
enum IdentifierNamespace {
|
enum IdentifierNamespace {
|
||||||
/// Labels, declared with 'x:' and referenced with 'goto x'.
|
IDNS_Label = 0x1,
|
||||||
IDNS_Label = 0x0001,
|
IDNS_Tag = 0x2,
|
||||||
|
IDNS_Member = 0x4,
|
||||||
/// Tags, declared with 'struct foo;' and referenced with
|
IDNS_Ordinary = 0x8,
|
||||||
/// 'struct foo'. All tags are also types. This is what
|
IDNS_ObjCProtocol = 0x10,
|
||||||
/// elaborated-type-specifiers look for in C.
|
IDNS_OrdinaryFriend = 0x80,
|
||||||
IDNS_Tag = 0x0002,
|
IDNS_TagFriend = 0x100,
|
||||||
|
IDNS_Using = 0x200
|
||||||
/// Types, declared with 'struct foo', typedefs, etc.
|
|
||||||
/// This is what elaborated-type-specifiers look for in C++,
|
|
||||||
/// but note that it's ill-formed to find a non-tag.
|
|
||||||
IDNS_Type = 0x0004,
|
|
||||||
|
|
||||||
/// Members, declared with object declarations within tag
|
|
||||||
/// definitions. In C, these can only be found by "qualified"
|
|
||||||
/// lookup in member expressions. In C++, they're found by
|
|
||||||
/// normal lookup.
|
|
||||||
IDNS_Member = 0x0008,
|
|
||||||
|
|
||||||
/// Namespaces, declared with 'namespace foo {}'.
|
|
||||||
/// Lookup for nested-name-specifiers find these.
|
|
||||||
IDNS_Namespace = 0x0010,
|
|
||||||
|
|
||||||
/// Ordinary names. In C, everything that's not a label, tag,
|
|
||||||
/// or member ends up here.
|
|
||||||
IDNS_Ordinary = 0x0020,
|
|
||||||
|
|
||||||
/// Objective C @protocol.
|
|
||||||
IDNS_ObjCProtocol = 0x0040,
|
|
||||||
|
|
||||||
/// This declaration is a friend function. A friend function
|
|
||||||
/// declaration is always in this namespace but may also be in
|
|
||||||
/// IDNS_Ordinary if it was previously declared.
|
|
||||||
IDNS_OrdinaryFriend = 0x0080,
|
|
||||||
|
|
||||||
/// This declaration is a friend class. A friend class
|
|
||||||
/// declaration is always in this namespace but may also be in
|
|
||||||
/// IDNS_Tag|IDNS_Type if it was previously declared.
|
|
||||||
IDNS_TagFriend = 0x0100,
|
|
||||||
|
|
||||||
/// This declaration is a using declaration. A using declaration
|
|
||||||
/// *introduces* a number of other declarations into the current
|
|
||||||
/// scope, and those declarations use the IDNS of their targets,
|
|
||||||
/// but the actual using declarations go in this namespace.
|
|
||||||
IDNS_Using = 0x0200
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ObjCDeclQualifier - Qualifier used on types in method declarations
|
/// ObjCDeclQualifier - Qualifier used on types in method declarations
|
||||||
|
@ -492,14 +453,14 @@ public:
|
||||||
assert((OldNS & (IDNS_Tag | IDNS_Ordinary |
|
assert((OldNS & (IDNS_Tag | IDNS_Ordinary |
|
||||||
IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
|
IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
|
||||||
"namespace includes neither ordinary nor tag");
|
"namespace includes neither ordinary nor tag");
|
||||||
assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | IDNS_Type |
|
assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary |
|
||||||
IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
|
IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
|
||||||
"namespace includes other than ordinary or tag");
|
"namespace includes other than ordinary or tag");
|
||||||
|
|
||||||
IdentifierNamespace = 0;
|
IdentifierNamespace = 0;
|
||||||
if (OldNS & (IDNS_Tag | IDNS_TagFriend)) {
|
if (OldNS & (IDNS_Tag | IDNS_TagFriend)) {
|
||||||
IdentifierNamespace |= IDNS_TagFriend;
|
IdentifierNamespace |= IDNS_TagFriend;
|
||||||
if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag | IDNS_Type;
|
if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) {
|
if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) {
|
||||||
|
|
|
@ -1583,11 +1583,6 @@ def err_redefinition_different_kind : Error<
|
||||||
"redefinition of %0 as different kind of symbol">;
|
"redefinition of %0 as different kind of symbol">;
|
||||||
def err_redefinition_different_typedef : Error<
|
def err_redefinition_different_typedef : Error<
|
||||||
"typedef redefinition with different types (%0 vs %1)">;
|
"typedef redefinition with different types (%0 vs %1)">;
|
||||||
def err_tag_reference_non_tag : Error<
|
|
||||||
"elaborated type refers to %select{a non-tag type|a typedef|a template}0">;
|
|
||||||
def err_tag_reference_conflict : Error<
|
|
||||||
"implicit declaration introduced by elaborated type conflicts with "
|
|
||||||
"%select{a declaration|a typedef|a template}0 of the same name">;
|
|
||||||
def err_tag_definition_of_typedef : Error<
|
def err_tag_definition_of_typedef : Error<
|
||||||
"definition of type %0 conflicts with typedef of the same name">;
|
"definition of type %0 conflicts with typedef of the same name">;
|
||||||
def err_conflicting_types : Error<"conflicting types for %0">;
|
def err_conflicting_types : Error<"conflicting types for %0">;
|
||||||
|
|
|
@ -1438,7 +1438,7 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
|
||||||
for (DeclContext::lookup_result Lookup = DC->lookup(Name);
|
for (DeclContext::lookup_result Lookup = DC->lookup(Name);
|
||||||
Lookup.first != Lookup.second;
|
Lookup.first != Lookup.second;
|
||||||
++Lookup.first) {
|
++Lookup.first) {
|
||||||
if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Namespace))
|
if (!(*Lookup.first)->isInIdentifierNamespace(Decl::IDNS_Ordinary))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (NamespaceDecl *FoundNS = dyn_cast<NamespaceDecl>(*Lookup.first)) {
|
if (NamespaceDecl *FoundNS = dyn_cast<NamespaceDecl>(*Lookup.first)) {
|
||||||
|
@ -1451,7 +1451,7 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ConflictingDecls.empty()) {
|
if (!ConflictingDecls.empty()) {
|
||||||
Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Namespace,
|
Name = Importer.HandleNameConflict(Name, DC, Decl::IDNS_Ordinary,
|
||||||
ConflictingDecls.data(),
|
ConflictingDecls.data(),
|
||||||
ConflictingDecls.size());
|
ConflictingDecls.size());
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,28 +231,23 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||||
case CXXConstructor:
|
case CXXConstructor:
|
||||||
case CXXDestructor:
|
case CXXDestructor:
|
||||||
case CXXConversion:
|
case CXXConversion:
|
||||||
|
case Typedef:
|
||||||
case EnumConstant:
|
case EnumConstant:
|
||||||
case Var:
|
case Var:
|
||||||
case ImplicitParam:
|
case ImplicitParam:
|
||||||
case ParmVar:
|
case ParmVar:
|
||||||
case NonTypeTemplateParm:
|
case NonTypeTemplateParm:
|
||||||
case ObjCMethod:
|
case ObjCMethod:
|
||||||
case ObjCProperty:
|
|
||||||
return IDNS_Ordinary;
|
|
||||||
|
|
||||||
case ObjCCompatibleAlias:
|
|
||||||
case ObjCInterface:
|
case ObjCInterface:
|
||||||
return IDNS_Ordinary | IDNS_Type;
|
case ObjCProperty:
|
||||||
|
case ObjCCompatibleAlias:
|
||||||
case Typedef:
|
return IDNS_Ordinary;
|
||||||
case UnresolvedUsingTypename:
|
|
||||||
case TemplateTypeParm:
|
|
||||||
return IDNS_Ordinary | IDNS_Type;
|
|
||||||
|
|
||||||
case UsingShadow:
|
case UsingShadow:
|
||||||
return 0; // we'll actually overwrite this later
|
return 0; // we'll actually overwrite this later
|
||||||
|
|
||||||
case UnresolvedUsingValue:
|
case UnresolvedUsingValue:
|
||||||
|
case UnresolvedUsingTypename:
|
||||||
return IDNS_Ordinary | IDNS_Using;
|
return IDNS_Ordinary | IDNS_Using;
|
||||||
|
|
||||||
case Using:
|
case Using:
|
||||||
|
@ -269,18 +264,15 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||||
case Record:
|
case Record:
|
||||||
case CXXRecord:
|
case CXXRecord:
|
||||||
case Enum:
|
case Enum:
|
||||||
return IDNS_Tag | IDNS_Type;
|
case TemplateTypeParm:
|
||||||
|
return IDNS_Tag;
|
||||||
|
|
||||||
case Namespace:
|
case Namespace:
|
||||||
case NamespaceAlias:
|
|
||||||
return IDNS_Namespace;
|
|
||||||
|
|
||||||
case FunctionTemplate:
|
case FunctionTemplate:
|
||||||
return IDNS_Ordinary;
|
|
||||||
|
|
||||||
case ClassTemplate:
|
case ClassTemplate:
|
||||||
case TemplateTemplateParm:
|
case TemplateTemplateParm:
|
||||||
return IDNS_Ordinary | IDNS_Tag | IDNS_Type;
|
case NamespaceAlias:
|
||||||
|
return IDNS_Tag | IDNS_Ordinary;
|
||||||
|
|
||||||
// Never have names.
|
// Never have names.
|
||||||
case Friend:
|
case Friend:
|
||||||
|
|
|
@ -415,9 +415,6 @@ bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Filter == &ResultBuilder::IsNestedNameSpecifier)
|
|
||||||
AsNestedNameSpecifier = true;
|
|
||||||
|
|
||||||
// ... then it must be interesting!
|
// ... then it must be interesting!
|
||||||
return true;
|
return true;
|
||||||
|
@ -507,8 +504,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
|
||||||
}
|
}
|
||||||
for (; I != IEnd; ++I) {
|
for (; I != IEnd; ++I) {
|
||||||
// A tag declaration does not hide a non-tag declaration.
|
// A tag declaration does not hide a non-tag declaration.
|
||||||
if (I->first->getIdentifierNamespace()
|
if (I->first->getIdentifierNamespace() == Decl::IDNS_Tag &&
|
||||||
== (Decl::IDNS_Tag | Decl::IDNS_Type) &&
|
|
||||||
(IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
|
(IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
|
||||||
Decl::IDNS_ObjCProtocol)))
|
Decl::IDNS_ObjCProtocol)))
|
||||||
continue;
|
continue;
|
||||||
|
@ -633,7 +629,7 @@ void ResultBuilder::ExitScope() {
|
||||||
bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
|
bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
|
||||||
unsigned IDNS = Decl::IDNS_Ordinary;
|
unsigned IDNS = Decl::IDNS_Ordinary;
|
||||||
if (SemaRef.getLangOptions().CPlusPlus)
|
if (SemaRef.getLangOptions().CPlusPlus)
|
||||||
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
|
IDNS |= Decl::IDNS_Tag;
|
||||||
else if (SemaRef.getLangOptions().ObjC1 && isa<ObjCIvarDecl>(ND))
|
else if (SemaRef.getLangOptions().ObjC1 && isa<ObjCIvarDecl>(ND))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -645,7 +641,7 @@ bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
|
||||||
bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
|
bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
|
||||||
unsigned IDNS = Decl::IDNS_Ordinary;
|
unsigned IDNS = Decl::IDNS_Ordinary;
|
||||||
if (SemaRef.getLangOptions().CPlusPlus)
|
if (SemaRef.getLangOptions().CPlusPlus)
|
||||||
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
|
IDNS |= Decl::IDNS_Tag;
|
||||||
|
|
||||||
return (ND->getIdentifierNamespace() & IDNS) &&
|
return (ND->getIdentifierNamespace() & IDNS) &&
|
||||||
!isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND);
|
!isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND);
|
||||||
|
@ -2098,16 +2094,10 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultBuilder Results(*this);
|
ResultBuilder Results(*this, Filter);
|
||||||
|
Results.allowNestedNameSpecifiers();
|
||||||
CodeCompletionDeclConsumer Consumer(Results, CurContext);
|
CodeCompletionDeclConsumer Consumer(Results, CurContext);
|
||||||
|
|
||||||
// First pass: look for tags.
|
|
||||||
Results.setFilter(Filter);
|
|
||||||
LookupVisibleDecls(S, LookupTagName, Consumer);
|
LookupVisibleDecls(S, LookupTagName, Consumer);
|
||||||
|
|
||||||
// Second pass: look for nested name specifiers.
|
|
||||||
Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
|
|
||||||
LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
|
|
||||||
|
|
||||||
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
|
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
|
||||||
}
|
}
|
||||||
|
|
|
@ -5000,8 +5000,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
||||||
SearchDC = SearchDC->getEnclosingNamespaceContext();
|
SearchDC = SearchDC->getEnclosingNamespaceContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
// In C++, we need to do a redeclaration lookup to properly
|
// In C++, look for a shadow friend decl.
|
||||||
// diagnose some problems.
|
|
||||||
if (getLangOptions().CPlusPlus) {
|
if (getLangOptions().CPlusPlus) {
|
||||||
Previous.setRedeclarationKind(ForRedeclaration);
|
Previous.setRedeclarationKind(ForRedeclaration);
|
||||||
LookupQualifiedName(Previous, SearchDC);
|
LookupQualifiedName(Previous, SearchDC);
|
||||||
|
@ -5010,26 +5009,6 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
||||||
|
|
||||||
if (!Previous.empty()) {
|
if (!Previous.empty()) {
|
||||||
NamedDecl *PrevDecl = (*Previous.begin())->getUnderlyingDecl();
|
NamedDecl *PrevDecl = (*Previous.begin())->getUnderlyingDecl();
|
||||||
|
|
||||||
// It's okay to have a tag decl in the same scope as a typedef
|
|
||||||
// which shadows a tag decl in the same scope. Finding this
|
|
||||||
// insanity with a redeclaration lookup can only actually happen
|
|
||||||
// in C++.
|
|
||||||
if (getLangOptions().CPlusPlus &&
|
|
||||||
TUK != TUK_Reference && TUK != TUK_Friend) {
|
|
||||||
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(PrevDecl)) {
|
|
||||||
if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
|
|
||||||
TagDecl *Tag = TT->getDecl();
|
|
||||||
if (Tag->getDeclName() == Name &&
|
|
||||||
Tag->getDeclContext()->Equals(SearchDC)) {
|
|
||||||
PrevDecl = Tag;
|
|
||||||
Previous.clear();
|
|
||||||
Previous.addDecl(Tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
|
if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
|
||||||
// If this is a use of a previous tag, or if the tag is already declared
|
// If this is a use of a previous tag, or if the tag is already declared
|
||||||
// in the same scope (so that the definition/declaration completes or
|
// in the same scope (so that the definition/declaration completes or
|
||||||
|
@ -5121,61 +5100,23 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
||||||
// If we get here, we're going to create a new Decl. If PrevDecl
|
// If we get here, we're going to create a new Decl. If PrevDecl
|
||||||
// is non-NULL, it's a definition of the tag declared by
|
// is non-NULL, it's a definition of the tag declared by
|
||||||
// PrevDecl. If it's NULL, we have a new definition.
|
// PrevDecl. If it's NULL, we have a new definition.
|
||||||
|
|
||||||
|
|
||||||
// Otherwise, PrevDecl is not a tag, but was found with tag
|
|
||||||
// lookup. This is only actually possible in C++, where a few
|
|
||||||
// things like templates still live in the tag namespace.
|
|
||||||
} else {
|
} else {
|
||||||
assert(getLangOptions().CPlusPlus);
|
// PrevDecl is a namespace, template, or anything else
|
||||||
|
// that lives in the IDNS_Tag identifier namespace.
|
||||||
// Use a better diagnostic if an elaborated-type-specifier
|
if (TUK == TUK_Reference || TUK == TUK_Friend ||
|
||||||
// found the wrong kind of type on the first
|
isDeclInScope(PrevDecl, SearchDC, S)) {
|
||||||
// (non-redeclaration) lookup.
|
// The tag name clashes with a namespace name, issue an error and
|
||||||
if ((TUK == TUK_Reference || TUK == TUK_Friend) &&
|
// recover by making this tag be anonymous.
|
||||||
!Previous.isForRedeclaration()) {
|
|
||||||
unsigned Kind = 0;
|
|
||||||
if (isa<TypedefDecl>(PrevDecl)) Kind = 1;
|
|
||||||
else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2;
|
|
||||||
Diag(NameLoc, diag::err_tag_reference_non_tag) << Kind;
|
|
||||||
Diag(PrevDecl->getLocation(), diag::note_declared_at);
|
|
||||||
Invalid = true;
|
|
||||||
|
|
||||||
// Otherwise, only diagnose if the declaration is in scope.
|
|
||||||
} else if (!isDeclInScope(PrevDecl, SearchDC, S)) {
|
|
||||||
// do nothing
|
|
||||||
|
|
||||||
// Diagnose implicit declarations introduced by elaborated types.
|
|
||||||
} else if (TUK == TUK_Reference || TUK == TUK_Friend) {
|
|
||||||
unsigned Kind = 0;
|
|
||||||
if (isa<TypedefDecl>(PrevDecl)) Kind = 1;
|
|
||||||
else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2;
|
|
||||||
Diag(NameLoc, diag::err_tag_reference_conflict) << Kind;
|
|
||||||
Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;
|
|
||||||
Invalid = true;
|
|
||||||
|
|
||||||
// Otherwise it's a declaration. Call out a particularly common
|
|
||||||
// case here.
|
|
||||||
} else if (isa<TypedefDecl>(PrevDecl)) {
|
|
||||||
Diag(NameLoc, diag::err_tag_definition_of_typedef)
|
|
||||||
<< Name
|
|
||||||
<< cast<TypedefDecl>(PrevDecl)->getUnderlyingType();
|
|
||||||
Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;
|
|
||||||
Invalid = true;
|
|
||||||
|
|
||||||
// Otherwise, diagnose.
|
|
||||||
} else {
|
|
||||||
// The tag name clashes with something else in the target scope,
|
|
||||||
// issue an error and recover by making this tag be anonymous.
|
|
||||||
Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
|
Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
|
||||||
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
||||||
Name = 0;
|
Name = 0;
|
||||||
|
Previous.clear();
|
||||||
Invalid = true;
|
Invalid = true;
|
||||||
|
} else {
|
||||||
|
// The existing declaration isn't relevant to us; we're in a
|
||||||
|
// new scope, so clear out the previous declaration.
|
||||||
|
Previous.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The existing declaration isn't relevant to us; we're in a
|
|
||||||
// new scope, so clear out the previous declaration.
|
|
||||||
Previous.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5246,6 +5187,28 @@ CreateNewDecl:
|
||||||
New->addAttr(::new (Context) PragmaPackAttr(Alignment * 8));
|
New->addAttr(::new (Context) PragmaPackAttr(Alignment * 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getLangOptions().CPlusPlus && SS.isEmpty() && Name && !Invalid) {
|
||||||
|
// C++ [dcl.typedef]p3:
|
||||||
|
// [...] Similarly, in a given scope, a class or enumeration
|
||||||
|
// shall not be declared with the same name as a typedef-name
|
||||||
|
// that is declared in that scope and refers to a type other
|
||||||
|
// than the class or enumeration itself.
|
||||||
|
LookupResult Lookup(*this, Name, NameLoc, LookupOrdinaryName,
|
||||||
|
ForRedeclaration);
|
||||||
|
LookupName(Lookup, S);
|
||||||
|
TypedefDecl *PrevTypedef = Lookup.getAsSingle<TypedefDecl>();
|
||||||
|
NamedDecl *PrevTypedefNamed = PrevTypedef;
|
||||||
|
if (PrevTypedef && isDeclInScope(PrevTypedefNamed, SearchDC, S) &&
|
||||||
|
Context.getCanonicalType(Context.getTypeDeclType(PrevTypedef)) !=
|
||||||
|
Context.getCanonicalType(Context.getTypeDeclType(New))) {
|
||||||
|
Diag(Loc, diag::err_tag_definition_of_typedef)
|
||||||
|
<< Context.getTypeDeclType(New)
|
||||||
|
<< PrevTypedef->getUnderlyingType();
|
||||||
|
Diag(PrevTypedef->getLocation(), diag::note_previous_definition);
|
||||||
|
Invalid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If this is a specialization of a member class (of a class template),
|
// If this is a specialization of a member class (of a class template),
|
||||||
// check the specialization.
|
// check the specialization.
|
||||||
if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous))
|
if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous))
|
||||||
|
|
|
@ -202,6 +202,26 @@ static bool IsAcceptableOperatorName(NamedDecl *D, unsigned IDNS) {
|
||||||
!D->getDeclContext()->isRecord();
|
!D->getDeclContext()->isRecord();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsAcceptableNestedNameSpecifierName(NamedDecl *D, unsigned IDNS) {
|
||||||
|
// This lookup ignores everything that isn't a type.
|
||||||
|
|
||||||
|
// This is a fast check for the far most common case.
|
||||||
|
if (D->isInIdentifierNamespace(Decl::IDNS_Tag))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (isa<UsingShadowDecl>(D))
|
||||||
|
D = cast<UsingShadowDecl>(D)->getTargetDecl();
|
||||||
|
|
||||||
|
return isa<TypeDecl>(D);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsAcceptableNamespaceName(NamedDecl *D, unsigned IDNS) {
|
||||||
|
// We don't need to look through using decls here because
|
||||||
|
// using decls aren't allowed to name namespaces.
|
||||||
|
|
||||||
|
return isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D);
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the default result filter for the given lookup.
|
/// Gets the default result filter for the given lookup.
|
||||||
static inline
|
static inline
|
||||||
LookupResult::ResultFilter getResultFilter(Sema::LookupNameKind NameKind) {
|
LookupResult::ResultFilter getResultFilter(Sema::LookupNameKind NameKind) {
|
||||||
|
@ -212,12 +232,16 @@ LookupResult::ResultFilter getResultFilter(Sema::LookupNameKind NameKind) {
|
||||||
case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping
|
case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping
|
||||||
case Sema::LookupUsingDeclName:
|
case Sema::LookupUsingDeclName:
|
||||||
case Sema::LookupObjCProtocolName:
|
case Sema::LookupObjCProtocolName:
|
||||||
case Sema::LookupNestedNameSpecifierName:
|
|
||||||
case Sema::LookupNamespaceName:
|
|
||||||
return &IsAcceptableIDNS;
|
return &IsAcceptableIDNS;
|
||||||
|
|
||||||
case Sema::LookupOperatorName:
|
case Sema::LookupOperatorName:
|
||||||
return &IsAcceptableOperatorName;
|
return &IsAcceptableOperatorName;
|
||||||
|
|
||||||
|
case Sema::LookupNestedNameSpecifierName:
|
||||||
|
return &IsAcceptableNestedNameSpecifierName;
|
||||||
|
|
||||||
|
case Sema::LookupNamespaceName:
|
||||||
|
return &IsAcceptableNamespaceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm_unreachable("unkknown lookup kind");
|
llvm_unreachable("unkknown lookup kind");
|
||||||
|
@ -236,25 +260,15 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
|
||||||
case Sema::LookupRedeclarationWithLinkage:
|
case Sema::LookupRedeclarationWithLinkage:
|
||||||
IDNS = Decl::IDNS_Ordinary;
|
IDNS = Decl::IDNS_Ordinary;
|
||||||
if (CPlusPlus) {
|
if (CPlusPlus) {
|
||||||
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Namespace;
|
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member;
|
||||||
if (Redeclaration) IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend;
|
if (Redeclaration) IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Sema::LookupTagName:
|
case Sema::LookupTagName:
|
||||||
if (CPlusPlus) {
|
IDNS = Decl::IDNS_Tag;
|
||||||
IDNS = Decl::IDNS_Type;
|
if (CPlusPlus && Redeclaration)
|
||||||
|
IDNS |= Decl::IDNS_TagFriend;
|
||||||
// When looking for a redeclaration of a tag name, we add:
|
|
||||||
// 1) TagFriend to find undeclared friend decls
|
|
||||||
// 2) Namespace because they can't "overload" with tag decls.
|
|
||||||
// 3) Tag because it includes class templates, which can't
|
|
||||||
// "overload" with tag decls.
|
|
||||||
if (Redeclaration)
|
|
||||||
IDNS |= Decl::IDNS_Tag | Decl::IDNS_TagFriend | Decl::IDNS_Namespace;
|
|
||||||
} else {
|
|
||||||
IDNS = Decl::IDNS_Tag;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Sema::LookupMemberName:
|
case Sema::LookupMemberName:
|
||||||
|
@ -264,11 +278,8 @@ static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Sema::LookupNestedNameSpecifierName:
|
case Sema::LookupNestedNameSpecifierName:
|
||||||
IDNS = Decl::IDNS_Type | Decl::IDNS_Namespace;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Sema::LookupNamespaceName:
|
case Sema::LookupNamespaceName:
|
||||||
IDNS = Decl::IDNS_Namespace;
|
IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Sema::LookupUsingDeclName:
|
case Sema::LookupUsingDeclName:
|
||||||
|
@ -2123,8 +2134,7 @@ NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) {
|
||||||
IEnd = Pos->second.end();
|
IEnd = Pos->second.end();
|
||||||
I != IEnd; ++I) {
|
I != IEnd; ++I) {
|
||||||
// A tag declaration does not hide a non-tag declaration.
|
// A tag declaration does not hide a non-tag declaration.
|
||||||
if ((*I)->getIdentifierNamespace()
|
if ((*I)->getIdentifierNamespace() == Decl::IDNS_Tag &&
|
||||||
== (Decl::IDNS_Tag|Decl::IDNS_Type) &&
|
|
||||||
(IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
|
(IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
|
||||||
Decl::IDNS_ObjCProtocol)))
|
Decl::IDNS_ObjCProtocol)))
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
|
||||||
|
|
||||||
namespace test0 {
|
|
||||||
struct A {
|
|
||||||
static int foo;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace i0 {
|
|
||||||
typedef int A; // expected-note {{declared here}}
|
|
||||||
|
|
||||||
int test() {
|
|
||||||
struct A a; // expected-error {{elaborated type refers to a typedef}}
|
|
||||||
return a.foo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace i1 {
|
|
||||||
template <class> class A; // expected-note {{declared here}}
|
|
||||||
|
|
||||||
int test() {
|
|
||||||
struct A a; // expected-error {{elaborated type refers to a template}}
|
|
||||||
return a.foo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace i2 {
|
|
||||||
int A;
|
|
||||||
|
|
||||||
int test() {
|
|
||||||
struct A a;
|
|
||||||
return a.foo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace i3 {
|
|
||||||
void A();
|
|
||||||
|
|
||||||
int test() {
|
|
||||||
struct A a;
|
|
||||||
return a.foo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace i4 {
|
|
||||||
template <class T> void A();
|
|
||||||
|
|
||||||
int test() {
|
|
||||||
struct A a;
|
|
||||||
return a.foo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -280,10 +280,3 @@ namespace test8 {
|
||||||
}
|
}
|
||||||
template A::I g2<A::I>(A::I i);
|
template A::I g2<A::I>(A::I i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PR6885
|
|
||||||
namespace test9 {
|
|
||||||
class B {
|
|
||||||
friend class test9;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
@ -155,7 +155,7 @@ namespace Dependent {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace test7 {
|
namespace test7 {
|
||||||
template <class T> class A { // expected-note {{declared here}}
|
template <class T> class A { // expected-note {{previous definition is here}}
|
||||||
friend class B;
|
friend class B;
|
||||||
int x; // expected-note {{declared private here}}
|
int x; // expected-note {{declared private here}}
|
||||||
};
|
};
|
||||||
|
@ -174,7 +174,7 @@ namespace test7 {
|
||||||
|
|
||||||
// This shouldn't crash.
|
// This shouldn't crash.
|
||||||
template <class T> class D {
|
template <class T> class D {
|
||||||
friend class A; // expected-error {{elaborated type refers to a template}}
|
friend class A; // expected-error {{redefinition of 'A' as different kind of symbol}}
|
||||||
};
|
};
|
||||||
template class D<int>;
|
template class D<int>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ struct X {
|
||||||
struct Y; // expected-note{{previous definition is here}}
|
struct Y; // expected-note{{previous definition is here}}
|
||||||
typedef int Y; // expected-error{{typedef redefinition with different types ('int' vs 'Y')}}
|
typedef int Y; // expected-error{{typedef redefinition with different types ('int' vs 'Y')}}
|
||||||
|
|
||||||
typedef int Y2; // expected-note{{declared here}}
|
typedef int Y2; // expected-note{{previous definition is here}}
|
||||||
struct Y2; // expected-error{{definition of type 'Y2' conflicts with typedef of the same name}}
|
struct Y2; // expected-error{{definition of type 'Y2' conflicts with typedef of the same name}}
|
||||||
|
|
||||||
void f(); // expected-note{{previous definition is here}}
|
void f(); // expected-note{{previous definition is here}}
|
||||||
|
|
Loading…
Reference in New Issue