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