r312743 - Add IDNS_Tag to C++ declarations that conflict with tag declarations.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 7 13:22:01 PDT 2017
Author: rsmith
Date: Thu Sep 7 13:22:00 2017
New Revision: 312743
URL: http://llvm.org/viewvc/llvm-project?rev=312743&view=rev
Log:
Add IDNS_Tag to C++ declarations that conflict with tag declarations.
Fixes some accepts-invalids with tags and other declarations declared in the
same scope.
Added:
cfe/trunk/test/CXX/basic/basic.scope/basic.scope.declarative/p4.cpp
Modified:
cfe/trunk/include/clang/AST/DeclBase.h
cfe/trunk/lib/AST/DeclBase.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=312743&r1=312742&r2=312743&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Thu Sep 7 13:22:00 2017
@@ -1002,13 +1002,15 @@ public:
/// declaration, but in the semantic context of the enclosing namespace
/// scope.
void setLocalExternDecl() {
- assert((IdentifierNamespace == IDNS_Ordinary ||
- IdentifierNamespace == IDNS_OrdinaryFriend) &&
- "namespace is not ordinary");
-
Decl *Prev = getPreviousDecl();
IdentifierNamespace &= ~IDNS_Ordinary;
+ // It's OK for the declaration to still have the "invisible friend" flag or
+ // the "conflicts with tag declarations in this scope" flag for the outer
+ // scope.
+ assert((IdentifierNamespace & ~(IDNS_OrdinaryFriend | IDNS_Tag)) == 0 &&
+ "namespace is not ordinary");
+
IdentifierNamespace |= IDNS_LocalExtern;
if (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary)
IdentifierNamespace |= IDNS_Ordinary;
Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=312743&r1=312742&r2=312743&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Thu Sep 7 13:22:00 2017
@@ -681,7 +681,6 @@ unsigned Decl::getIdentifierNamespaceFor
case CXXConversion:
case EnumConstant:
case Var:
- case Binding:
case ImplicitParam:
case ParmVar:
case ObjCMethod:
@@ -693,10 +692,11 @@ unsigned Decl::getIdentifierNamespaceFor
case IndirectField:
return IDNS_Ordinary | IDNS_Member;
+ case Binding:
case NonTypeTemplateParm:
- // Non-type template parameters are not found by lookups that ignore
- // non-types, but they are found by redeclaration lookups for tag types,
- // so we include them in the tag namespace.
+ case VarTemplate:
+ // These (C++-only) declarations are found by redeclaration lookup for
+ // tag types, so we include them in the tag namespace.
return IDNS_Ordinary | IDNS_Tag;
case ObjCCompatibleAlias:
@@ -705,7 +705,6 @@ unsigned Decl::getIdentifierNamespaceFor
case Typedef:
case TypeAlias:
- case TypeAliasTemplate:
case TemplateTypeParm:
case ObjCTypeParam:
return IDNS_Ordinary | IDNS_Type;
@@ -741,11 +740,11 @@ unsigned Decl::getIdentifierNamespaceFor
return IDNS_Namespace;
case FunctionTemplate:
- case VarTemplate:
return IDNS_Ordinary;
case ClassTemplate:
case TemplateTemplateParm:
+ case TypeAliasTemplate:
return IDNS_Ordinary | IDNS_Tag | IDNS_Type;
case OMPDeclareReduction:
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=312743&r1=312742&r2=312743&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Sep 7 13:22:00 2017
@@ -5288,13 +5288,6 @@ NamedDecl *Sema::HandleDeclarator(Scope
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType R = TInfo->getType();
- if (!R->isFunctionType() && DiagnoseClassNameShadow(DC, NameInfo))
- // If this is a typedef, we'll end up spewing multiple diagnostics.
- // Just return early; it's safer. If this is a function, let the
- // "constructor cannot have a return type" diagnostic handle it.
- if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
- return nullptr;
-
if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
UPPC_DeclarationType))
D.setInvalidType();
@@ -5373,12 +5366,17 @@ NamedDecl *Sema::HandleDeclarator(Scope
Previous.clear();
}
+ if (!R->isFunctionType() && DiagnoseClassNameShadow(DC, NameInfo))
+ // Forget that the previous declaration is the injected-class-name.
+ Previous.clear();
+
// In C++, the previous declaration we find might be a tag type
// (class or enum). In this case, the new declaration will hide the
- // tag type. Note that this does does not apply if we're declaring a
- // typedef (C++ [dcl.typedef]p4).
+ // tag type. Note that this applies to functions, function templates, and
+ // variables, but not to typedefs (C++ [dcl.typedef]p4) or variable templates.
if (Previous.isSingleTagDecl() &&
- D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef)
+ D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
+ (TemplateParamLists.size() == 0 || R->isFunctionType()))
Previous.clear();
// Check that there are no default arguments other than in the parameters
Added: cfe/trunk/test/CXX/basic/basic.scope/basic.scope.declarative/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.scope/basic.scope.declarative/p4.cpp?rev=312743&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.scope/basic.scope.declarative/p4.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.scope/basic.scope.declarative/p4.cpp Thu Sep 7 13:22:00 2017
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+namespace TagVs {
+ struct Bindable { int a; };
+ struct binding_a {}; // expected-note {{previous}}
+ auto [binding_a] = Bindable{}; // expected-error {{redefinition}}
+ auto [binding_b] = Bindable{}; // expected-note {{previous}}
+ struct binding_b {}; // expected-error {{redefinition}}
+
+ struct vartemplate_a {}; // expected-note {{previous}}
+ template<typename T> int vartemplate_a; // expected-error {{redefinition}}
+ template<typename T> int vartemplate_b; // expected-note {{previous}}
+ struct vartemplate_b {}; // expected-error {{redefinition}}
+
+ struct aliastemplate_a {}; // expected-note {{previous}}
+ template<typename T> using aliastemplate_a = int; // expected-error {{redefinition}}
+ template<typename T> using aliastemplate_b = int; // expected-note {{previous}}
+ struct aliastemplate_b {}; // expected-error {{redefinition}}
+}
More information about the cfe-commits
mailing list