hokein updated this revision to Diff 488403.
hokein marked 2 inline comments as done.
hokein added a comment.

address comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141280/new/

https://reviews.llvm.org/D141280

Files:
  clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
  clang/include/clang/Sema/DeclSpec.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaTemplate.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/CXX/drs/dr2xx.cpp
  clang/test/CXX/drs/dr4xx.cpp
  clang/test/SemaCXX/using-decl-1.cpp

Index: clang/test/SemaCXX/using-decl-1.cpp
===================================================================
--- clang/test/SemaCXX/using-decl-1.cpp
+++ clang/test/SemaCXX/using-decl-1.cpp
@@ -177,6 +177,10 @@
 
     struct S {
       friend struct HiddenTag1; // expected-error {{tag type that does not match previous}}
+#if __cplusplus < 201103L
+    // expected-warning@-2 {{befriending enumeration type 'struct HiddenTag1' is a C++11 extension}}
+#endif
+
       friend struct HiddenTag2; // expected-note {{conflicting declaration}}
       friend void HiddenFn1(); // expected-error {{cannot befriend target of using declaration}}
       friend void HiddenFn2(); // expected-note {{conflicting declaration}}
Index: clang/test/CXX/drs/dr4xx.cpp
===================================================================
--- clang/test/CXX/drs/dr4xx.cpp
+++ clang/test/CXX/drs/dr4xx.cpp
@@ -301,9 +301,8 @@
     struct F;
     struct H;
   }
-  // FIXME: This is ill-formed.
   using N::D;
-  struct dr417::D {}; // expected-warning {{extra qualification}}
+  struct dr417::D {}; // expected-error {{forward declaration of struct cannot}} expected-warning {{extra qualification}}
   using namespace N;
   struct dr417::E {}; // expected-warning {{extra qualification}} expected-error {{no struct named 'E'}}
   struct N::F {};
@@ -311,7 +310,7 @@
   using N::H;
   namespace M {
     struct dr417::G {}; // expected-error {{namespace 'M' does not enclose}}
-    struct dr417::H {}; // expected-error {{namespace 'M' does not enclose}}
+    struct dr417::H {}; // expected-error {{namespace 'M' does not enclose}} expected-error {{forward declaration of struct cannot have}}
   }
 }
 
Index: clang/test/CXX/drs/dr2xx.cpp
===================================================================
--- clang/test/CXX/drs/dr2xx.cpp
+++ clang/test/CXX/drs/dr2xx.cpp
@@ -992,7 +992,7 @@
   }
   struct B::V {}; // expected-error {{no struct named 'V'}}
   struct B::W {};
-  struct B::X {}; // FIXME: ill-formed
+  struct B::X {}; // expected-error {{forward declaration of struct cannot have}}
   enum B::Y e; // ok per dr417
   class B::Z z; // ok per dr417
 
@@ -1009,7 +1009,7 @@
   };
   struct D::V {}; // expected-error {{no struct named 'V'}}
   struct D::W {};
-  struct D::X {}; // FIXME: ill-formed
+  struct D::X {}; // expected-error {{forward declaration of struct cannot have}}
   enum D::Y e2; // ok per dr417
   class D::Z z2; // ok per dr417
 }
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -1587,6 +1587,9 @@
 
     // TypeQuals handled by caller.
     Result = Context.getTypeDeclType(D);
+    if (const auto *Using =
+            dyn_cast_or_null<UsingShadowDecl>(DS.getRepAsFoundDecl()))
+      Result = Context.getUsingType(Using, Result);
 
     // In both C and C++, make an ElaboratedType.
     ElaboratedTypeKeyword Keyword
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -10180,13 +10180,15 @@
 
   bool Owned = false;
   bool IsDependent = false;
+  UsingShadowDecl* FoundUsing = nullptr;
   Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference,
                         KWLoc, SS, Name, NameLoc, Attr, AS_none,
                         /*ModulePrivateLoc=*/SourceLocation(),
                         MultiTemplateParamsArg(), Owned, IsDependent,
                         SourceLocation(), false, TypeResult(),
                         /*IsTypeSpecifier*/false,
-                        /*IsTemplateParamOrArg*/false);
+                        /*IsTemplateParamOrArg*/false,
+                        FoundUsing);
   assert(!IsDependent && "explicit instantiation of dependent name not yet handled");
 
   if (!TagD)
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -16964,6 +16964,7 @@
     if (SS.isEmpty()) {
       bool Owned = false;
       bool IsDependent = false;
+      UsingShadowDecl* FoundUsing = nullptr;
       return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc,
                       Attr, AS_public,
                       /*ModulePrivateLoc=*/SourceLocation(),
@@ -16972,7 +16973,8 @@
                       /*ScopedEnumUsesClassTag=*/false,
                       /*UnderlyingType=*/TypeResult(),
                       /*IsTypeSpecifier=*/false,
-                      /*IsTemplateParamOrArg=*/false);
+                      /*IsTemplateParamOrArg=*/false,
+                      FoundUsing);
     }
 
     NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -16573,6 +16573,7 @@
                      SourceLocation ScopedEnumKWLoc,
                      bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
                      bool IsTypeSpecifier, bool IsTemplateParamOrArg,
+                     UsingShadowDecl*& FoundUsingShadow,
                      SkipBodyInfo *SkipBody) {
   // If this is not a definition, it must have a name.
   IdentifierInfo *OrigName = Name;
@@ -17008,6 +17009,7 @@
     // redefinition if either context is within the other.
     if (auto *Shadow = dyn_cast<UsingShadowDecl>(DirectPrevDecl)) {
       auto *OldTag = dyn_cast<TagDecl>(PrevDecl);
+      FoundUsingShadow = Shadow;
       if (SS.isEmpty() && TUK != TUK_Reference && TUK != TUK_Friend &&
           isDeclInScope(Shadow, SearchDC, S, isMemberSpecialization) &&
           !(OldTag && isAcceptableTagRedeclContext(
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -1933,6 +1933,7 @@
   // Create the tag portion of the class or class template.
   DeclResult TagOrTempResult = true; // invalid
   TypeResult TypeResult = true;      // invalid
+  UsingShadowDecl *FoundUsing = nullptr;
 
   bool Owned = false;
   Sema::SkipBodyInfo SkipBody;
@@ -2073,8 +2074,7 @@
         DSC == DeclSpecContext::DSC_type_specifier,
         DSC == DeclSpecContext::DSC_template_param ||
             DSC == DeclSpecContext::DSC_template_type_arg,
-        &SkipBody);
-
+        FoundUsing, &SkipBody);
     // If ActOnTag said the type was dependent, try again with the
     // less common call.
     if (IsDependent) {
@@ -2130,9 +2130,11 @@
                                 NameLoc.isValid() ? NameLoc : StartLoc,
                                 PrevSpec, DiagID, TypeResult.get(), Policy);
   } else if (!TagOrTempResult.isInvalid()) {
+    // FIXME: !! TagOrTempResult.get() can be a nullptr here, this looks
+    // suspicious.
     Result = DS.SetTypeSpecType(
         TagType, StartLoc, NameLoc.isValid() ? NameLoc : StartLoc, PrevSpec,
-        DiagID, TagOrTempResult.get(), Owned, Policy);
+        DiagID, FoundUsing ? FoundUsing : TagOrTempResult.get(), Owned, Policy);
   } else {
     DS.SetTypeSpecError();
     return;
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -4965,6 +4965,7 @@
   bool IsDependent = false;
   const char *PrevSpec = nullptr;
   unsigned DiagID;
+  UsingShadowDecl* FoundUsing = nullptr;
   Decl *TagDecl = Actions.ActOnTag(
       getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc,
       attrs, AS, DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent,
@@ -4972,7 +4973,7 @@
       DSC == DeclSpecContext::DSC_type_specifier,
       DSC == DeclSpecContext::DSC_template_param ||
           DSC == DeclSpecContext::DSC_template_type_arg,
-      &SkipBody);
+      FoundUsing, &SkipBody);
 
   if (SkipBody.ShouldSkip) {
     assert(TUK == Sema::TUK_Definition && "can only skip a definition");
@@ -4982,8 +4983,8 @@
     T.skipToEnd();
 
     if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
-                           NameLoc.isValid() ? NameLoc : StartLoc,
-                           PrevSpec, DiagID, TagDecl, Owned,
+                           NameLoc.isValid() ? NameLoc : StartLoc, PrevSpec,
+                           DiagID, FoundUsing ? FoundUsing : TagDecl, Owned,
                            Actions.getASTContext().getPrintingPolicy()))
       Diag(StartLoc, DiagID) << PrevSpec;
     return;
@@ -5037,8 +5038,8 @@
   }
 
   if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
-                         NameLoc.isValid() ? NameLoc : StartLoc,
-                         PrevSpec, DiagID, TagDecl, Owned,
+                         NameLoc.isValid() ? NameLoc : StartLoc, PrevSpec,
+                         DiagID, FoundUsing ? FoundUsing : TagDecl, Owned,
                          Actions.getASTContext().getPrintingPolicy()))
     Diag(StartLoc, DiagID) << PrevSpec;
 }
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -3312,6 +3312,7 @@
                  bool &IsDependent, SourceLocation ScopedEnumKWLoc,
                  bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
                  bool IsTypeSpecifier, bool IsTemplateParamOrArg,
+                 UsingShadowDecl*& FoundUsingShadow,
                  SkipBodyInfo *SkipBody = nullptr);
 
   Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
Index: clang/include/clang/Sema/DeclSpec.h
===================================================================
--- clang/include/clang/Sema/DeclSpec.h
+++ clang/include/clang/Sema/DeclSpec.h
@@ -506,8 +506,16 @@
     assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
     return TypeRep;
   }
+  // Returns the underlying decl, if any.
   Decl *getRepAsDecl() const {
-    assert(isDeclRep((TST) TypeSpecType) && "DeclSpec does not store a decl");
+    auto *D = getRepAsFoundDecl();
+    if (const auto *Using = dyn_cast_or_null<UsingShadowDecl>(D))
+      return Using->getTargetDecl();
+    return D;
+  }
+  // Returns the originally found decl, if any.
+  Decl *getRepAsFoundDecl() const {
+    assert(isDeclRep((TST)TypeSpecType) && "DeclSpec does not store a decl");
     return DeclRep;
   }
   Expr *getRepAsExpr() const {
Index: clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
===================================================================
--- clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
@@ -150,6 +150,9 @@
     }
     using ns::$explicit^Y;)cpp",
            "^Y<int> x;");
+  testWalk(R"cpp(
+    namespace ns { class Foo {}; }
+  )cpp", "using ns::$explicit^Foo; class ^Foo foo;");
 }
 
 TEST(WalkAST, Namespaces) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to