]> granicus.if.org Git - clang/commitdiff
Switch parsing of using declarations over to ParseUnqualifiedId.
authorDouglas Gregor <dgregor@apple.com>
Wed, 4 Nov 2009 16:30:06 +0000 (16:30 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 4 Nov 2009 16:30:06 +0000 (16:30 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86027 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticParseKinds.td
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Parse/Action.h
lib/Parse/MinimalAction.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Sema/Sema.h
lib/Sema/SemaDeclCXX.cpp
test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp

index db8d580a2cd7a569ff4fe01cf9fdda129451a4e5..e173cffdfd2bb48213bedf6ccafa74f6ba4372ef 100644 (file)
@@ -166,9 +166,6 @@ def err_use_of_tag_name_without_tag : Error<
   "use of tagged type %0 without '%1' tag">;
 def err_expected_ident_in_using : Error<
   "expected an identifier in using directive">;
-def err_using_decl_can_not_refer_to_template_spec : Error<
-  "using declaration can not refer to template specialization">;
-
 
 /// Objective-C parser diagnostics
 def err_objc_no_attributes_on_category : Error<
index 99fddb581088a7435c5278f15f1faf7da9b5bb70..368496975ad9d649f879f67facdcf82cd26c0614 100644 (file)
@@ -107,8 +107,14 @@ def err_using_decl_nested_name_specifier_is_not_a_base_class : Error<
   "using declaration refers into '%0', which is not a base class of %1">;
 def err_using_decl_can_not_refer_to_class_member : Error<
   "using declaration can not refer to class member">;
- def err_using_decl_can_not_refer_to_namespace : Error<
+def err_using_decl_can_not_refer_to_namespace : Error<
   "using declaration can not refer to namespace">;
+def err_using_decl_constructor : Error<
+  "using declaration can not refer to a constructor">;
+def err_using_decl_destructor : Error<
+  "using declaration can not refer to a destructor">;
+def err_using_decl_template_id : Error<
+  "using declaration can not refer to a template specialization">;
 
 def err_invalid_thread : Error<
   "'__thread' is only allowed on variable declarations">;
index 073365dcede366485980c4f688d15288c5254188..657a14fff0828de4aa86ad7afff7a35ee2acf1e1 100644 (file)
@@ -1174,14 +1174,41 @@ public:
     return DeclPtrTy();
   }
 
-  /// ActOnUsingDirective - This is called when using-directive is parsed.
+  /// \brief Parsed a C++ using-declaration.
+  ///
+  /// This callback will be invoked when the parser has parsed a C++
+  /// using-declaration, e.g.,
+  ///
+  /// \code
+  /// namespace std {
+  ///   template<typename T, typename Alloc> class vector;
+  /// }
+  ///
+  /// using std::vector; // using-declaration here
+  /// \endcode
+  ///
+  /// \param CurScope the scope in which this using declaration was parsed.
+  ///
+  /// \param AS the currently-active access specifier.
+  ///
+  /// \param UsingLoc the location of the 'using' keyword.
+  ///
+  /// \param SS the nested-name-specifier that precedes the name.
+  ///
+  /// \param Name the name to which the using declaration refers.
+  ///
+  /// \param AttrList attributes applied to this using declaration, if any.
+  ///
+  /// \param IsTypeName whether this using declaration started with the 
+  /// 'typename' keyword. FIXME: This will eventually be split into a 
+  /// separate action.
+  ///
+  /// \returns a representation of the using declaration.
   virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
                                           AccessSpecifier AS,
                                           SourceLocation UsingLoc,
                                           const CXXScopeSpec &SS,
-                                          SourceLocation IdentLoc,
-                                          IdentifierInfo *TargetName,
-                                          OverloadedOperatorKind Op,
+                                          UnqualifiedId &Name,
                                           AttributeList *AttrList,
                                           bool IsTypeName);
 
index 1e7d397fdf3775e2255dc6af90e63990eb35dbd5..bf05b2baccd4f86ef327791fef0e17ba7cf41d3f 100644 (file)
@@ -42,14 +42,12 @@ Action::DeclPtrTy Action::ActOnUsingDirective(Scope *CurScope,
   return DeclPtrTy();
 }
 
-// Defined out-of-line here because of dependecy on AttributeList
+// Defined out-of-line here because of dependency on AttributeList
 Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope,
                                                 AccessSpecifier AS,
                                                 SourceLocation UsingLoc,
                                                 const CXXScopeSpec &SS,
-                                                SourceLocation IdentLoc,
-                                                IdentifierInfo *TargetName,
-                                                OverloadedOperatorKind Op,
+                                                UnqualifiedId &Name,
                                                 AttributeList *AttrList,
                                                 bool IsTypeName) {
 
index 91f86864f81fd9b86b31c50e1448331e5c8bcd5d..154c2923486e14a4f629a996a8056dda70e97382 100644 (file)
@@ -285,6 +285,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
   bool IsTypeName;
 
   // Ignore optional 'typename'.
+  // FIXME: This is wrong; we should parse this as a typename-specifier.
   if (Tok.is(tok::kw_typename)) {
     ConsumeToken();
     IsTypeName = true;
@@ -302,41 +303,21 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
     SkipUntil(tok::semi);
     return DeclPtrTy();
   }
-  if (Tok.is(tok::annot_template_id)) {
-    // C++0x N2914 [namespace.udecl]p5:
-    // A using-declaration shall not name a template-id.
-    Diag(Tok, diag::err_using_decl_can_not_refer_to_template_spec);
-    SkipUntil(tok::semi);
-    return DeclPtrTy();
-  }
-
-  IdentifierInfo *TargetName = 0;
-  OverloadedOperatorKind Op = OO_None;
-  SourceLocation IdentLoc;
 
-  if (Tok.is(tok::kw_operator)) {
-    IdentLoc = Tok.getLocation();
-
-    Op = TryParseOperatorFunctionId();
-    if (!Op) {
-      // If there was an invalid operator, skip to end of decl, and eat ';'.
-      SkipUntil(tok::semi);
-      return DeclPtrTy();
-    }
-    // FIXME: what about conversion functions?
-  } else if (Tok.is(tok::identifier)) {
-    // Parse identifier.
-    TargetName = Tok.getIdentifierInfo();
-    IdentLoc = ConsumeToken();
-  } else {
-    // FIXME: Use a better diagnostic here.
-    Diag(Tok, diag::err_expected_ident_in_using);
-
-    // If there was invalid identifier, skip to end of decl, and eat ';'.
+  // Parse the unqualified-id. We allow parsing of both constructor and 
+  // destructor names and allow the action module to diagnose any semantic
+  // errors.
+  UnqualifiedId Name;
+  if (ParseUnqualifiedId(SS, 
+                         /*EnteringContext=*/false,
+                         /*AllowDestructorName=*/true,
+                         /*AllowConstructorName=*/true, 
+                         /*ObjectType=*/0, 
+                         Name)) {
     SkipUntil(tok::semi);
     return DeclPtrTy();
   }
-
+  
   // Parse (optional) attributes (most likely GNU strong-using extension).
   if (Tok.is(tok::kw___attribute))
     AttrList = ParseAttributes();
@@ -344,10 +325,10 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
   // Eat ';'.
   DeclEnd = Tok.getLocation();
   ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
-                   AttrList ? "attributes list" : "namespace name", tok::semi);
+                   AttrList ? "attributes list" : "using declaration", 
+                   tok::semi);
 
-  return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS,
-                                       IdentLoc, TargetName, Op,
+  return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS, Name,
                                        AttrList, IsTypeName);
 }
 
index 0f84b46ed405694dfc4b1223a2e3ad83f66f2124..b0aa7b747305cc31021418ae71913c47a893acba 100644 (file)
@@ -1893,9 +1893,7 @@ public:
                                           AccessSpecifier AS,
                                           SourceLocation UsingLoc,
                                           const CXXScopeSpec &SS,
-                                          SourceLocation IdentLoc,
-                                          IdentifierInfo *TargetName,
-                                          OverloadedOperatorKind Op,
+                                          UnqualifiedId &Name,
                                           AttributeList *AttrList,
                                           bool IsTypeName);
 
index bc255137fccf980665a77dfe1ba3dd6de70c5205..3314ee26cb1437662fe327737dbd9312cf4fec7b 100644 (file)
@@ -2700,22 +2700,37 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
                                             AccessSpecifier AS,
                                             SourceLocation UsingLoc,
                                             const CXXScopeSpec &SS,
-                                            SourceLocation IdentLoc,
-                                            IdentifierInfo *TargetName,
-                                            OverloadedOperatorKind Op,
+                                            UnqualifiedId &Name,
                                             AttributeList *AttrList,
                                             bool IsTypeName) {
-  assert((TargetName || Op) && "Invalid TargetName.");
   assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
 
-  DeclarationName Name;
-  if (TargetName)
-    Name = TargetName;
-  else
-    Name = Context.DeclarationNames.getCXXOperatorName(Op);
-
-  NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS, IdentLoc,
-                                        Name, AttrList, IsTypeName);
+  switch (Name.getKind()) {
+  case UnqualifiedId::IK_Identifier:
+  case UnqualifiedId::IK_OperatorFunctionId:
+  case UnqualifiedId::IK_ConversionFunctionId:
+    break;
+      
+  case UnqualifiedId::IK_ConstructorName:
+    Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_constructor)
+      << SS.getRange();
+    return DeclPtrTy();
+      
+  case UnqualifiedId::IK_DestructorName:
+    Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_destructor)
+      << SS.getRange();
+    return DeclPtrTy();
+      
+  case UnqualifiedId::IK_TemplateId:
+    Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_template_id)
+      << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
+    return DeclPtrTy();
+  }
+  
+  DeclarationName TargetName = GetNameFromUnqualifiedId(Name);
+  NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS, 
+                                        Name.getSourceRange().getBegin(),
+                                        TargetName, AttrList, IsTypeName);
   if (UD) {
     PushOnScopeChains(UD, S);
     UD->setAccess(AS);
index 63e5c3cd27b0a3029650bafe2b4ac2a006254149..31218c41300f53a76fba4f8d65e5c5c2bdf9554f 100644 (file)
@@ -7,6 +7,6 @@ struct A {
 };
 
 struct B : A {
-  using A::f<double>; // expected-error{{using declaration can not refer to template specialization}}
-  using A::X<int>; // expected-error{{using declaration can not refer to template specialization}}
-};
\ No newline at end of file
+  using A::f<double>; // expected-error{{using declaration can not refer to a template specialization}}
+  using A::X<int>; // expected-error{{using declaration can not refer to a template specialization}}
+};