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}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits