[cfe-commits] r102247 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Parse/ParseDecl.cpp lib/Sema/SemaCXXScopeSpec.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp test/SemaTemplate/elaborated-type-specifier.cpp

Douglas Gregor dgregor at apple.com
Sat Apr 24 09:38:41 PDT 2010


Author: dgregor
Date: Sat Apr 24 11:38:41 2010
New Revision: 102247

URL: http://llvm.org/viewvc/llvm-project?rev=102247&view=rev
Log:
Be more careful around dependent nested-name-specifiers, complaining
when they are not complete (since we could not match them up to
anything) and ensuring that enum parsing can cope with dependent
elaborated-type-specifiers. Fixes PR6915 and PR6649.


Added:
    cfe/trunk/test/SemaTemplate/elaborated-type-specifier.cpp   (with props)
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=102247&r1=102246&r2=102247&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Apr 24 11:38:41 2010
@@ -513,6 +513,9 @@
 // C++ name lookup
 def err_incomplete_nested_name_spec : Error<
   "incomplete type %0 named in nested name specifier">;
+def err_dependent_nested_name_spec : Error<
+  "nested name specifier for a declaration cannot depend on a template "
+  "parameter">;
 def err_nested_name_member_ref_lookup_ambiguous : Error<
   "lookup of %0 in member access expression is ambiguous">;
 def note_ambig_member_ref_object_type : Note<
@@ -1590,6 +1593,9 @@
 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_dependent_tag_decl : Error<
+  "%select{declaration|definition}0 of %select{struct|union|class|enum}1 "
+  "in a dependent scope">;
 def err_tag_definition_of_typedef : Error<
   "definition of type %0 conflicts with typedef of the same name">;
 def err_conflicting_types : Error<"conflicting types for %0">;

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=102247&r1=102246&r2=102247&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sat Apr 24 11:38:41 2010
@@ -1934,21 +1934,55 @@
     TUK = Action::TUK_Reference;
   bool Owned = false;
   bool IsDependent = false;
+  SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc;
+  const char *PrevSpec = 0;
+  unsigned DiagID;
   DeclPtrTy TagDecl = Actions.ActOnTag(CurScope, DeclSpec::TST_enum, TUK,
                                        StartLoc, SS, Name, NameLoc, Attr.get(),
                                        AS,
                                        Action::MultiTemplateParamsArg(Actions),
                                        Owned, IsDependent);
-  assert(!IsDependent && "didn't expect dependent enum");
+  if (IsDependent) {
+    // This enum has a dependent nested-name-specifier. Handle it as a 
+    // dependent tag.
+    if (!Name) {
+      DS.SetTypeSpecError();
+      Diag(Tok, diag::err_expected_type_name_after_typename);
+      return;
+    }
+    
+    TypeResult Type = Actions.ActOnDependentTag(CurScope, DeclSpec::TST_enum,
+                                                TUK, SS, Name, StartLoc, 
+                                                NameLoc);
+    if (Type.isInvalid()) {
+      DS.SetTypeSpecError();
+      return;
+    }
+    
+    if (DS.SetTypeSpecType(DeclSpec::TST_typename, TSTLoc, PrevSpec, DiagID,
+                           Type.get(), false))
+      Diag(StartLoc, DiagID) << PrevSpec;
+    
+    return;
+  }
 
+  if (!TagDecl.get()) {
+    // The action failed to produce an enumeration tag. If this is a 
+    // definition, consume the entire definition.
+    if (Tok.is(tok::l_brace)) {
+      ConsumeBrace();
+      SkipUntil(tok::r_brace);
+    }
+    
+    DS.SetTypeSpecError();
+    return;
+  }
+  
   if (Tok.is(tok::l_brace))
     ParseEnumBody(StartLoc, TagDecl);
 
   // FIXME: The DeclSpec should keep the locations of both the keyword and the
   // name (if there is one).
-  SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc;
-  const char *PrevSpec = 0;
-  unsigned DiagID;
   if (DS.SetTypeSpecType(DeclSpec::TST_enum, TSTLoc, PrevSpec, DiagID,
                          TagDecl.getAs<void>(), Owned))
     Diag(StartLoc, DiagID) << PrevSpec;

Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=102247&r1=102246&r2=102247&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Sat Apr 24 11:38:41 2010
@@ -235,6 +235,16 @@
     return false;
 
   DeclContext *DC = computeDeclContext(SS, true);
+  if (!DC) {
+    // It's dependent.
+    assert(isDependentScopeSpecifier(SS) && 
+           "No context for non-dependent scope specifier?");
+    Diag(SS.getRange().getBegin(), diag::err_dependent_nested_name_spec)
+      << SS.getRange();
+    SS.setScopeRep(0);
+    return true;
+  }
+  
   if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
     // If this is a dependent type, then we consider it complete.
     if (Tag->isDependentContext())

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=102247&r1=102246&r2=102247&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Apr 24 11:38:41 2010
@@ -5313,7 +5313,7 @@
 void Sema::ActOnTagStartDefinition(Scope *S, DeclPtrTy TagD) {
   AdjustDeclIfTemplate(TagD);
   TagDecl *Tag = cast<TagDecl>(TagD.getAs<Decl>());
-
+  
   // Enter the tag context.
   PushDeclContext(S, Tag);
 }

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=102247&r1=102246&r2=102247&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sat Apr 24 11:38:41 2010
@@ -5117,6 +5117,13 @@
   }
   assert(Keyword != ETK_None && "Invalid tag kind!");
 
+  if (TUK == TUK_Declaration || TUK == TUK_Definition) {
+    Diag(NameLoc, diag::err_dependent_tag_decl)
+      << (TUK == TUK_Definition) << TagDecl::getTagKindForTypeSpec(TagSpec)
+      << SS.getRange();
+    return true;
+  }
+  
   return Context.getDependentNameType(Keyword, NNS, Name).getAsOpaquePtr();
 }
 

Added: cfe/trunk/test/SemaTemplate/elaborated-type-specifier.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/elaborated-type-specifier.cpp?rev=102247&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/elaborated-type-specifier.cpp (added)
+++ cfe/trunk/test/SemaTemplate/elaborated-type-specifier.cpp Sat Apr 24 11:38:41 2010
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+namespace PR6915 {
+  template <typename T>
+  class D {
+    enum T::X v; // expected-error{{use of 'X' with tag type that does not match previous declaration}} \
+    // expected-error{{no enum named 'X' in 'PR6915::D3'}}
+  };
+
+  struct D1 {
+    enum X { value };
+  };
+  struct D2 { 
+    class X { }; // expected-note{{previous use is here}}
+  };
+  struct D3 { };
+
+  template class D<D1>;
+  template class D<D2>; // expected-note{{in instantiation of}}
+  template class D<D3>; // expected-note{{in instantiation of}}
+}
+
+template<typename T>
+struct DeclOrDef {
+  enum T::foo; // expected-error{{nested name specifier for a declaration cannot depend on a template parameter}}
+  enum T::bar { // expected-error{{nested name specifier for a declaration cannot depend on a template parameter}}
+    value 
+  };
+};
+
+namespace PR6649 {
+  template <typename T> struct foo { 
+    class T::bar;  // expected-error{{nested name specifier for a declaration cannot depend on a template parameter}}
+  };
+}

Propchange: cfe/trunk/test/SemaTemplate/elaborated-type-specifier.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/SemaTemplate/elaborated-type-specifier.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/SemaTemplate/elaborated-type-specifier.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list