[cfe-commits] r85851 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Parse/DeclSpec.h include/clang/Parse/Parser.h lib/Parse/DeclSpec.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseExprCXX.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaType.cpp test/CXX/temp/temp.spec/temp.explicit/p3.cpp test/SemaCXX/constructor.cpp test/SemaTemplate/constructor-template.cpp

Douglas Gregor dgregor at apple.com
Mon Nov 2 17:35:08 PST 2009


Author: dgregor
Date: Mon Nov  2 19:35:08 2009
New Revision: 85851

URL: http://llvm.org/viewvc/llvm-project?rev=85851&view=rev
Log:
Introduce a new class, UnqualifiedId, that provides a parsed
representation of a C++ unqualified-id, along with a single parsing
function (Parser::ParseUnqualifiedId) that will parse all of the
various forms of unqualified-id in C++.

Replace the representation of the declarator name in Declarator with
the new UnqualifiedId class, simplifying declarator-id parsing
considerably and providing more source-location information to
Sema. In the future, I hope to migrate all of the other
unqualified-id-parsing code over to this single representation, then
begin to merge actions that are currently only different because we
didn't have a unqualified notion of the name in the parser.


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Parse/DeclSpec.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/DeclSpec.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
    cfe/trunk/test/SemaCXX/constructor.cpp
    cfe/trunk/test/SemaTemplate/constructor-template.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=85851&r1=85850&r2=85851&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Mon Nov  2 19:35:08 2009
@@ -292,7 +292,9 @@
 // C++ declarations
 def err_friend_decl_defines_class : Error<
   "cannot define a type in a friend declaration">;
-
+def warn_operator_template_id_ignores_args : Error<
+  "clang bug: ignoring template arguments provided for operator">;
+  
 // Language specific pragmas
 // - Generic warnings
 def warn_pragma_expected_lparen : Warning<

Modified: cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=85851&r1=85850&r2=85851&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Mon Nov  2 19:35:08 2009
@@ -459,6 +459,193 @@
   }
 };
 
+/// \brief Represents a C++ unqualified-id that has been parsed. 
+class UnqualifiedId {
+private:
+  const UnqualifiedId &operator=(const UnqualifiedId &); // DO NOT IMPLEMENT
+  
+public:
+  /// \brief Describes the kind of unqualified-id parsed.
+  enum IdKind {
+    /// \brief An identifier.
+    IK_Identifier,
+    /// \brief An overloaded operator name, e.g., operator+.
+    IK_OperatorFunctionId,
+    /// \brief A conversion function name, e.g., operator int.
+    IK_ConversionFunctionId,
+    /// \brief A constructor name.
+    IK_ConstructorName,
+    /// \brief A destructor name.
+    IK_DestructorName,
+    /// \brief A template-id, e.g., f<int>.
+    IK_TemplateId
+  } Kind;
+
+  /// \brief Anonymous union that holds extra data associated with the
+  /// parsed unqualified-id.
+  union {
+    /// \brief When Kind == IK_Identifier, the parsed identifier.
+    IdentifierInfo *Identifier;
+    
+    /// \brief When Kind == IK_OperatorFunctionId, the overloaded operator
+    /// that we parsed.
+    struct {
+      /// \brief The kind of overloaded operator.
+      OverloadedOperatorKind Operator;
+      
+      /// \brief The source locations of the individual tokens that name
+      /// the operator, e.g., the "new", "[", and "]" tokens in 
+      /// operator new []. 
+      ///
+      /// Different operators have different numbers of tokens in their name,
+      /// up to three. Any remaining source locations in this array will be
+      /// set to an invalid value for operators with fewer than three tokens.
+      unsigned SymbolLocations[3];
+    } OperatorFunctionId;
+    
+    /// \brief When Kind == IK_ConversionFunctionId, the type that the 
+    /// conversion function names.
+    ActionBase::TypeTy *ConversionFunctionId;
+
+    /// \brief When Kind == IK_ConstructorName, the class-name of the type
+    /// whose constructor is being referenced.
+    ActionBase::TypeTy *ConstructorName;
+    
+    /// \brief When Kind == IK_DestructorName, the type referred to by the
+    /// class-name.
+    ActionBase::TypeTy *DestructorName;
+    
+    /// \brief When Kind == IK_TemplateId, the template-id annotation that
+    /// contains the template name and template arguments.
+    TemplateIdAnnotation *TemplateId;
+  };
+  
+  /// \brief The location of the first token that describes this unqualified-id,
+  /// which will be the location of the identifier, "operator" keyword,
+  /// tilde (for a destructor), or the template name of a template-id.
+  SourceLocation StartLocation;
+  
+  /// \brief The location of the last token that describes this unqualified-id.
+  SourceLocation EndLocation;
+  
+  UnqualifiedId() : Kind(IK_Identifier), Identifier(0) { }
+  
+  /// \brief Do not use this copy constructor. It is temporary, and only
+  /// exists because we are holding FieldDeclarators in a SmallVector when we
+  /// don't actually need them.
+  ///
+  /// FIXME: Kill this copy constructor.
+  UnqualifiedId(const UnqualifiedId &Other) 
+    : Kind(IK_Identifier), Identifier(Other.Identifier), 
+      StartLocation(Other.StartLocation), EndLocation(Other.EndLocation) {
+    assert(Other.Kind == IK_Identifier && "Cannot copy non-identifiers");
+  }
+
+  /// \brief Destroy this unqualified-id.
+  ~UnqualifiedId() { clear(); }
+  
+  /// \brief Clear out this unqualified-id, setting it to default (invalid) 
+  /// state.
+  void clear();
+  
+  /// \brief Determine whether this unqualified-id refers to a valid name.
+  bool isValid() const { return StartLocation.isValid(); }
+
+  /// \brief Determine whether this unqualified-id refers to an invalid name.
+  bool isInvalid() const { return !isValid(); }
+  
+  /// \brief Determine what kind of name we have.
+  IdKind getKind() const { return Kind; }
+  
+  /// \brief Specify that this unqualified-id was parsed as an identifier.
+  ///
+  /// \param Id the parsed identifier.
+  /// \param IdLoc the location of the parsed identifier.
+  void setIdentifier(IdentifierInfo *Id, SourceLocation IdLoc) {
+    Kind = IK_Identifier;
+    Identifier = Id;
+    StartLocation = EndLocation = IdLoc;
+  }
+  
+  /// \brief Specify that this unqualified-id was parsed as an 
+  /// operator-function-id.
+  ///
+  /// \param OperatorLoc the location of the 'operator' keyword.
+  ///
+  /// \param Op the overloaded operator.
+  ///
+  /// \param SymbolLocations the locations of the individual operator symbols
+  /// in the operator.
+  void setOperatorFunctionId(SourceLocation OperatorLoc, 
+                             OverloadedOperatorKind Op,
+                             SourceLocation SymbolLocations[3]);
+  
+  /// \brief Specify that this unqualified-id was parsed as a 
+  /// conversion-function-id.
+  ///
+  /// \param OperatorLoc the location of the 'operator' keyword.
+  ///
+  /// \param Ty the type to which this conversion function is converting.
+  ///
+  /// \param EndLoc the location of the last token that makes up the type name.
+  void setConversionFunctionId(SourceLocation OperatorLoc, 
+                               ActionBase::TypeTy *Ty,
+                               SourceLocation EndLoc) {
+    Kind = IK_ConversionFunctionId;
+    StartLocation = OperatorLoc;
+    EndLocation = EndLoc;
+    ConversionFunctionId = Ty;
+  }
+  
+  /// \brief Specify that this unqualified-id was parsed as a constructor name.
+  ///
+  /// \param ClassType the class type referred to by the constructor name.
+  ///
+  /// \param ClassNameLoc the location of the class name.
+  ///
+  /// \param EndLoc the location of the last token that makes up the type name.
+  void setConstructorName(ActionBase::TypeTy *ClassType, 
+                          SourceLocation ClassNameLoc,
+                          SourceLocation EndLoc) {
+    Kind = IK_ConstructorName;
+    StartLocation = ClassNameLoc;
+    EndLocation = EndLoc;
+    ConstructorName = ClassType;
+  }
+
+  /// \brief Specify that this unqualified-id was parsed as a destructor name.
+  ///
+  /// \param TildeLoc the location of the '~' that introduces the destructor
+  /// name.
+  ///
+  /// \param ClassType the name of the class referred to by the destructor name.
+  void setDestructorName(SourceLocation TildeLoc, ActionBase::TypeTy *ClassType,
+                         SourceLocation EndLoc) {
+    Kind = IK_DestructorName;
+    StartLocation = TildeLoc;
+    EndLocation = EndLoc;
+    DestructorName = ClassType;
+  }
+  
+  /// \brief Specify that this unqualified-id was parsed as a template-id.
+  ///
+  /// \param TemplateId the template-id annotation that describes the parsed
+  /// template-id. This UnqualifiedId instance will take ownership of the
+  /// \p TemplateId and will free it on destruction.
+  void setTemplateId(TemplateIdAnnotation *TemplateId) {
+    assert(TemplateId && "NULL template-id annotation?");
+    Kind = IK_TemplateId;
+    this->TemplateId = TemplateId;
+    StartLocation = TemplateId->TemplateNameLoc;
+    EndLocation = TemplateId->RAngleLoc;
+  }
+
+  /// \brief Return the source range that covers this unqualified-id.
+  SourceRange getSourceRange() const { 
+    return SourceRange(StartLocation, EndLocation); 
+  }
+};
+  
 /// CachedTokens - A set of tokens that has been cached for later
 /// parsing.
 typedef llvm::SmallVector<Token, 4> CachedTokens;
@@ -793,33 +980,16 @@
     BlockLiteralContext  // Block literal declarator.
   };
 
-  /// DeclaratorKind - The kind of declarator this represents.
-  enum DeclaratorKind {
-    DK_Abstract,         // An abstract declarator (has no identifier)
-    DK_Normal,           // A normal declarator (has an identifier).
-    DK_Constructor,      // A C++ constructor (identifier is the class name)
-    DK_Destructor,       // A C++ destructor  (identifier is ~class name)
-    DK_Operator,         // A C++ overloaded operator name
-    DK_Conversion,       // A C++ conversion function (identifier is
-                         // "operator " then the type name)
-    DK_TemplateId        // A C++ template-id naming a function template
-                         // specialization.
-  };
-
 private:
   const DeclSpec &DS;
   CXXScopeSpec SS;
-  IdentifierInfo *Identifier;
-  SourceLocation IdentifierLoc;
+  UnqualifiedId Name;
   SourceRange Range;
 
   /// Context - Where we are parsing this declarator.
   ///
   TheContext Context;
 
-  /// Kind - What kind of declarator this is.
-  DeclaratorKind Kind;
-
   /// DeclTypeInfo - This holds each type that the declarator includes as it is
   /// parsed.  This is pushed from the identifier out, which means that element
   /// #0 will be the most closely bound to the identifier, and
@@ -838,21 +1008,6 @@
   /// AsmLabel - The asm label, if specified.
   ActionBase::ExprTy *AsmLabel;
 
-  union {
-    // When Kind is DK_Constructor, DK_Destructor, or DK_Conversion, the
-    // type associated with the constructor, destructor, or conversion
-    // operator.
-    ActionBase::TypeTy *Type;
-
-    /// When Kind is DK_Operator, this is the actual overloaded
-    /// operator that this declarator names.
-    OverloadedOperatorKind OperatorKind;
-    
-    /// When Kind is DK_TemplateId, this is the template-id annotation that
-    /// contains the template and its template arguments.
-    TemplateIdAnnotation *TemplateId;
-  };
-
   /// InlineParams - This is a local array used for the first function decl
   /// chunk to avoid going to the heap for the common case when we have one
   /// function chunk in the declarator.
@@ -866,10 +1021,9 @@
 
 public:
   Declarator(const DeclSpec &ds, TheContext C)
-    : DS(ds), Identifier(0), Range(ds.getSourceRange()), Context(C),
-      Kind(DK_Abstract),
+    : DS(ds), Range(ds.getSourceRange()), Context(C),
       InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error),
-      GroupingParens(false), AttrList(0), AsmLabel(0), Type(0),
+      GroupingParens(false), AttrList(0), AsmLabel(0),
       InlineParamsUsed(false), Extension(false) {
   }
 
@@ -893,8 +1047,10 @@
   const CXXScopeSpec &getCXXScopeSpec() const { return SS; }
   CXXScopeSpec &getCXXScopeSpec() { return SS; }
 
+  /// \brief Retrieve the name specified by this declarator.
+  UnqualifiedId &getName() { return Name; }
+  
   TheContext getContext() const { return Context; }
-  DeclaratorKind getKind() const { return Kind; }
 
   /// getSourceRange - Get the source range that spans this declarator.
   const SourceRange &getSourceRange() const { return Range; }
@@ -925,22 +1081,15 @@
   /// clear - Reset the contents of this Declarator.
   void clear() {
     SS.clear();
-    Identifier = 0;
-    IdentifierLoc = SourceLocation();
+    Name.clear();
     Range = DS.getSourceRange();
     
-    if (Kind == DK_TemplateId)
-      TemplateId->Destroy();
-    
-    Kind = DK_Abstract;
-
     for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i)
       DeclTypeInfo[i].destroy();
     DeclTypeInfo.clear();
     delete AttrList;
     AttrList = 0;
     AsmLabel = 0;
-    Type = 0;
     InlineParamsUsed = false;
   }
 
@@ -971,84 +1120,28 @@
 
   /// isPastIdentifier - Return true if we have parsed beyond the point where
   /// the
-  bool isPastIdentifier() const { return IdentifierLoc.isValid(); }
+  bool isPastIdentifier() const { return Name.isValid(); }
 
   /// hasName - Whether this declarator has a name, which might be an
   /// identifier (accessible via getIdentifier()) or some kind of
   /// special C++ name (constructor, destructor, etc.).
-  bool hasName() const { return getKind() != DK_Abstract; }
-
-  IdentifierInfo *getIdentifier() const { return Identifier; }
-  SourceLocation getIdentifierLoc() const { return IdentifierLoc; }
-
-  void SetIdentifier(IdentifierInfo *ID, SourceLocation Loc) {
-    Identifier = ID;
-    IdentifierLoc = Loc;
-    if (ID)
-      Kind = DK_Normal;
-    else
-      Kind = DK_Abstract;
-    SetRangeEnd(Loc);
-  }
-
-  /// setConstructor - Set this declarator to be a C++ constructor
-  /// declarator. Also extends the range.
-  void setConstructor(ActionBase::TypeTy *Ty, SourceLocation Loc) {
-    IdentifierLoc = Loc;
-    Kind = DK_Constructor;
-    Type = Ty;
-    SetRangeEnd(Loc);
-  }
-
-  /// setDestructor - Set this declarator to be a C++ destructor
-  /// declarator. Also extends the range to End, which should be the identifier
-  /// token.
-  void setDestructor(ActionBase::TypeTy *Ty, SourceLocation Loc,
-                     SourceLocation EndLoc) {
-    IdentifierLoc = Loc;
-    Kind = DK_Destructor;
-    Type = Ty;
-    if (!EndLoc.isInvalid())
-      SetRangeEnd(EndLoc);
+  bool hasName() const { 
+    return Name.getKind() != UnqualifiedId::IK_Identifier || Name.Identifier;
   }
 
-  /// setConversionFunction - Set this declarator to be a C++
-  /// conversion function declarator (e.g., @c operator int const *).
-  /// Also extends the range to EndLoc, which should be the last token of the
-  /// type name.
-  void setConversionFunction(ActionBase::TypeTy *Ty, SourceLocation Loc,
-                             SourceLocation EndLoc) {
-    Identifier = 0;
-    IdentifierLoc = Loc;
-    Kind = DK_Conversion;
-    Type = Ty;
-    if (!EndLoc.isInvalid())
-      SetRangeEnd(EndLoc);
+  IdentifierInfo *getIdentifier() const { 
+    if (Name.getKind() == UnqualifiedId::IK_Identifier)
+      return Name.Identifier;
+    
+    return 0;
   }
+  SourceLocation getIdentifierLoc() const { return Name.StartLocation; }
 
-  /// setOverloadedOperator - Set this declaration to be a C++
-  /// overloaded operator declarator (e.g., @c operator+).
-  /// Also extends the range to EndLoc, which should be the last token of the
-  /// operator.
-  void setOverloadedOperator(OverloadedOperatorKind Op, SourceLocation Loc,
-                             SourceLocation EndLoc) {
-    IdentifierLoc = Loc;
-    Kind = DK_Operator;
-    OperatorKind = Op;
-    if (!EndLoc.isInvalid())
-      SetRangeEnd(EndLoc);
+  /// \brief Set the name of this declarator to be the given identifier.
+  void SetIdentifier(IdentifierInfo *Id, SourceLocation IdLoc) {
+    Name.setIdentifier(Id, IdLoc);
   }
-
-  /// \brief Set this declaration to be a C++ template-id, which includes the
-  /// template (or set of function templates) along with template arguments.
-  void setTemplateId(TemplateIdAnnotation *TemplateId) {
-    assert(TemplateId && "NULL template-id provided to declarator?");
-    IdentifierLoc = TemplateId->TemplateNameLoc;
-    Kind = DK_TemplateId;
-    SetRangeEnd(TemplateId->RAngleLoc);
-    this->TemplateId = TemplateId;
-  }
-                     
+  
   /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
   /// EndLoc, which should be the last token of the chunk.
   void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) {
@@ -1118,22 +1211,6 @@
   void setExtension(bool Val = true) { Extension = Val; }
   bool getExtension() const { return Extension; }
 
-  ActionBase::TypeTy *getDeclaratorIdType() const { 
-    assert((Kind == DK_Constructor || Kind == DK_Destructor || 
-            Kind == DK_Conversion) && "Declarator kind does not have a type");
-    return Type; 
-  }
-
-  OverloadedOperatorKind getOverloadedOperator() const { 
-    assert(Kind == DK_Operator && "Declarator is not an overloaded operator");
-    return OperatorKind; 
-  }
-
-  TemplateIdAnnotation *getTemplateId() { 
-    assert(Kind == DK_TemplateId && "Declarator is not a template-id");
-    return TemplateId;
-  }
-  
   void setInvalidType(bool Val = true) { InvalidType = Val; }
   bool isInvalidType() const {
     return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error;
@@ -1152,7 +1229,7 @@
     BitfieldSize = 0;
   }
 };
-
+  
 } // end namespace clang
 
 #endif

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=85851&r1=85850&r2=85851&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Nov  2 19:35:08 2009
@@ -1203,6 +1203,16 @@
   BaseResult ParseBaseSpecifier(DeclPtrTy ClassDecl);
   AccessSpecifier getAccessSpecifierIfPresent() const;
 
+  bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, 
+                                    IdentifierInfo *Name,
+                                    SourceLocation NameLoc,
+                                    bool EnteringContext,
+                                    UnqualifiedId &Id);
+  bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
+                          bool IsExpressionContext,
+                          bool IsDeclarator,
+                          UnqualifiedId &Result);
+    
   //===--------------------------------------------------------------------===//
   // C++ 13.5: Overloaded operators [over.oper]
   // EndLoc, if non-NULL, is filled with the location of the last token of

Modified: cfe/trunk/lib/Parse/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/DeclSpec.cpp?rev=85851&r1=85850&r2=85851&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Parse/DeclSpec.cpp Mon Nov  2 19:35:08 2009
@@ -446,3 +446,28 @@
        || tst == TST_enum
           ) && getTypeRep() != 0 && StorageClassSpec != DeclSpec::SCS_typedef;
 }
+
+void UnqualifiedId::clear() {
+  if (Kind == IK_TemplateId)
+    TemplateId->Destroy();
+  
+  Kind = IK_Identifier;
+  Identifier = 0;
+  StartLocation = SourceLocation();
+  EndLocation = SourceLocation();
+}
+
+void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc, 
+                                          OverloadedOperatorKind Op,
+                                          SourceLocation SymbolLocations[3]) {
+  Kind = IK_OperatorFunctionId;
+  StartLocation = OperatorLoc;
+  EndLocation = OperatorLoc;
+  OperatorFunctionId.Operator = Op;
+  for (unsigned I = 0; I != 3; ++I) {
+    OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding();
+    
+    if (SymbolLocations[I].isValid())
+      EndLocation = SymbolLocations[I];
+  }
+}

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=85851&r1=85850&r2=85851&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Nov  2 19:35:08 2009
@@ -2270,97 +2270,46 @@
 void Parser::ParseDirectDeclarator(Declarator &D) {
   DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
 
-  if (getLang().CPlusPlus) {
-    if (D.mayHaveIdentifier()) {
-      // ParseDeclaratorInternal might already have parsed the scope.
-      bool afterCXXScope = D.getCXXScopeSpec().isSet() ||
-        ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
-                                       true);
-      if (afterCXXScope) {
-        // Change the declaration context for name lookup, until this function
-        // is exited (and the declarator has been parsed).
-        DeclScopeObj.EnterDeclaratorScope();
-      }
-
-      if (Tok.is(tok::identifier)) {
-        assert(Tok.getIdentifierInfo() && "Not an identifier?");
-
-        // If this identifier is the name of the current class, it's a
-        // constructor name.
-        if (!D.getDeclSpec().hasTypeSpecifier() &&
-            Actions.isCurrentClassName(*Tok.getIdentifierInfo(),CurScope)) {
-          CXXScopeSpec *SS = afterCXXScope? &D.getCXXScopeSpec() : 0;
-          D.setConstructor(Actions.getTypeName(*Tok.getIdentifierInfo(),
-                                               Tok.getLocation(), CurScope, SS),
-                           Tok.getLocation());
-        // This is a normal identifier.
-        } else
-          D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
-        ConsumeToken();
-        goto PastIdentifier;
-      } else if (Tok.is(tok::annot_template_id)) {
-        TemplateIdAnnotation *TemplateId
-          = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
-
-        D.setTemplateId(TemplateId);
-        ConsumeToken();
-        goto PastIdentifier;
-      } else if (Tok.is(tok::kw_operator)) {
-        SourceLocation OperatorLoc = Tok.getLocation();
-        SourceLocation EndLoc;
-
-        // First try the name of an overloaded operator
-        if (OverloadedOperatorKind Op = TryParseOperatorFunctionId(&EndLoc)) {
-          D.setOverloadedOperator(Op, OperatorLoc, EndLoc);
-        } else {
-          // This must be a conversion function (C++ [class.conv.fct]).
-          if (TypeTy *ConvType = ParseConversionFunctionId(&EndLoc))
-            D.setConversionFunction(ConvType, OperatorLoc, EndLoc);
-          else {
-            D.SetIdentifier(0, Tok.getLocation());
-          }
-        }
-        goto PastIdentifier;
-      } else if (Tok.is(tok::tilde)) {
-        // This should be a C++ destructor.
-        SourceLocation TildeLoc = ConsumeToken();
-        if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) {
-          // FIXME: Inaccurate.
-          SourceLocation NameLoc = Tok.getLocation();
-          SourceLocation EndLoc;
-          CXXScopeSpec *SS = afterCXXScope? &D.getCXXScopeSpec() : 0;
-          TypeResult Type = ParseClassName(EndLoc, SS, true);
-          if (Type.isInvalid())
-            D.SetIdentifier(0, TildeLoc);
-          else
-            D.setDestructor(Type.get(), TildeLoc, NameLoc);
-        } else {
-          Diag(Tok, diag::err_destructor_class_name);
-          D.SetIdentifier(0, TildeLoc);
-        }
-        goto PastIdentifier;
-      }
-
-      // If we reached this point, token is not identifier and not '~'.
-
-      if (afterCXXScope) {
-        Diag(Tok, diag::err_expected_unqualified_id);
+  if (getLang().CPlusPlus && D.mayHaveIdentifier()) {
+    // ParseDeclaratorInternal might already have parsed the scope.
+    bool afterCXXScope = D.getCXXScopeSpec().isSet() ||
+      ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
+                                     true);
+    if (afterCXXScope) {
+      // Change the declaration context for name lookup, until this function
+      // is exited (and the declarator has been parsed).
+      DeclScopeObj.EnterDeclaratorScope();
+    } 
+    
+    if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) ||
+        Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) {
+      // We found something that indicates the start of an unqualified-id.
+      // Parse that unqualified-id.
+      if (ParseUnqualifiedId(D.getCXXScopeSpec(), 
+                             /*EnteringContext=*/true, 
+                             /*AllowDestructorName=*/true, 
+                   /*AllowConstructorName=*/!D.getDeclSpec().hasTypeSpecifier(), 
+                             D.getName())) {
         D.SetIdentifier(0, Tok.getLocation());
         D.setInvalidType(true);
-        goto PastIdentifier;
+      } else {
+        // Parsed the unqualified-id; update range information and move along.
+        if (D.getSourceRange().getBegin().isInvalid())
+          D.SetRangeBegin(D.getName().getSourceRange().getBegin());
+        D.SetRangeEnd(D.getName().getSourceRange().getEnd());
       }
+      goto PastIdentifier;
     }
-  }
-
-  // If we reached this point, we are either in C/ObjC or the token didn't
-  // satisfy any of the C++-specific checks.
-  if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {
+  } else if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {
     assert(!getLang().CPlusPlus &&
            "There's a C++-specific check for tok::identifier above");
     assert(Tok.getIdentifierInfo() && "Not an identifier?");
     D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
     ConsumeToken();
-  } else if (Tok.is(tok::l_paren)) {
+    goto PastIdentifier;
+  }
+    
+  if (Tok.is(tok::l_paren)) {
     // direct-declarator: '(' declarator ')'
     // direct-declarator: '(' attributes declarator ')'
     // Example: 'char (*X)'   or 'int (*XX)(void)'

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=85851&r1=85850&r2=85851&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Nov  2 19:35:08 2009
@@ -323,6 +323,7 @@
       SkipUntil(tok::semi);
       return DeclPtrTy();
     }
+    // FIXME: what about conversion functions?
   } else if (Tok.is(tok::identifier)) {
     // Parse identifier.
     TargetName = Tok.getIdentifierInfo();

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=85851&r1=85850&r2=85851&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Mon Nov  2 19:35:08 2009
@@ -14,6 +14,8 @@
 #include "clang/Parse/ParseDiagnostic.h"
 #include "clang/Parse/Parser.h"
 #include "clang/Parse/DeclSpec.h"
+#include "llvm/Support/ErrorHandling.h"
+
 using namespace clang;
 
 /// \brief Parse global scope or nested-name-specifier if present.
@@ -761,6 +763,417 @@
   return false;
 }
 
+/// \brief Finish parsing a C++ unqualified-id that is a template-id of
+/// some form. 
+///
+/// This routine is invoked when a '<' is encountered after an identifier or
+/// operator-function-id is parsed by \c ParseUnqualifiedId() to determine
+/// whether the unqualified-id is actually a template-id. This routine will
+/// then parse the template arguments and form the appropriate template-id to
+/// return to the caller.
+///
+/// \param SS the nested-name-specifier that precedes this template-id, if
+/// we're actually parsing a qualified-id.
+///
+/// \param Name for constructor and destructor names, this is the actual
+/// identifier that may be a template-name.
+///
+/// \param NameLoc the location of the class-name in a constructor or 
+/// destructor.
+///
+/// \param EnteringContext whether we're entering the scope of the 
+/// nested-name-specifier.
+///
+/// \param Id as input, describes the template-name or operator-function-id
+/// that precedes the '<'. If template arguments were parsed successfully,
+/// will be updated with the template-id.
+/// 
+/// \returns true if a parse error occurred, false otherwise.
+bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
+                                          IdentifierInfo *Name,
+                                          SourceLocation NameLoc,
+                                          bool EnteringContext,
+                                          UnqualifiedId &Id) {
+  assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id");
+  
+  TemplateTy Template;
+  TemplateNameKind TNK = TNK_Non_template;
+  switch (Id.getKind()) {
+  case UnqualifiedId::IK_Identifier:
+    TNK = Actions.isTemplateName(CurScope, *Id.Identifier, Id.StartLocation, 
+                                 &SS, /*ObjectType=*/0, EnteringContext,
+                                 Template);
+    break;
+      
+  case UnqualifiedId::IK_OperatorFunctionId: {
+    // FIXME: Temporary hack: warn that we are completely ignoring the 
+    // template arguments for now.
+    // Parse the enclosed template argument list.
+    SourceLocation LAngleLoc, RAngleLoc;
+    TemplateArgList TemplateArgs;
+    TemplateArgIsTypeList TemplateArgIsType;
+    TemplateArgLocationList TemplateArgLocations;
+    if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation,
+                                         &SS, true, LAngleLoc,
+                                         TemplateArgs,
+                                         TemplateArgIsType,
+                                         TemplateArgLocations,
+                                         RAngleLoc))
+      return true;
+    
+    Diag(Id.StartLocation, diag::warn_operator_template_id_ignores_args)
+      << SourceRange(LAngleLoc, RAngleLoc);
+    break;
+  }
+      
+  case UnqualifiedId::IK_ConstructorName:
+    TNK = Actions.isTemplateName(CurScope, *Name, NameLoc, 
+                                 &SS, /*ObjectType=*/0, EnteringContext,
+                                 Template);
+    break;
+      
+  case UnqualifiedId::IK_DestructorName:
+    TNK = Actions.isTemplateName(CurScope, *Name, NameLoc,
+                                 &SS, /*ObjectType=*/0, EnteringContext,
+                                 Template);
+    break;
+      
+  default:
+    return false;
+  }
+  
+  if (TNK == TNK_Non_template)
+    return false;
+  
+  // Parse the enclosed template argument list.
+  SourceLocation LAngleLoc, RAngleLoc;
+  TemplateArgList TemplateArgs;
+  TemplateArgIsTypeList TemplateArgIsType;
+  TemplateArgLocationList TemplateArgLocations;
+  if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation,
+                                       &SS, true, LAngleLoc,
+                                       TemplateArgs,
+                                       TemplateArgIsType,
+                                       TemplateArgLocations,
+                                       RAngleLoc))
+    return true;
+  
+  if (Id.getKind() == UnqualifiedId::IK_Identifier ||
+      Id.getKind() == UnqualifiedId::IK_OperatorFunctionId) {
+    // Form a parsed representation of the template-id to be stored in the
+    // UnqualifiedId.
+    TemplateIdAnnotation *TemplateId
+      = TemplateIdAnnotation::Allocate(TemplateArgs.size());
+
+    if (Id.getKind() == UnqualifiedId::IK_Identifier) {
+      TemplateId->Name = Id.Identifier;
+      TemplateId->TemplateNameLoc = Id.StartLocation;
+    } else {
+      // FIXME: Handle IK_OperatorFunctionId
+    }
+
+    TemplateId->Template = Template.getAs<void*>();
+    TemplateId->Kind = TNK;
+    TemplateId->LAngleLoc = LAngleLoc;
+    TemplateId->RAngleLoc = RAngleLoc;
+    void **Args = TemplateId->getTemplateArgs();
+    bool *ArgIsType = TemplateId->getTemplateArgIsType();
+    SourceLocation *ArgLocs = TemplateId->getTemplateArgLocations();
+    for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); 
+         Arg != ArgEnd; ++Arg) {
+      Args[Arg] = TemplateArgs[Arg];
+      ArgIsType[Arg] = TemplateArgIsType[Arg];
+      ArgLocs[Arg] = TemplateArgLocations[Arg];
+    }
+    
+    Id.setTemplateId(TemplateId);
+    return false;
+  }
+
+  // Bundle the template arguments together.
+  ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
+                                     TemplateArgIsType.data(),
+                                     TemplateArgs.size());
+  
+  // Constructor and destructor names.
+  Action::TypeResult Type
+    = Actions.ActOnTemplateIdType(Template, NameLoc,
+                                  LAngleLoc, TemplateArgsPtr,
+                                  &TemplateArgLocations[0],
+                                  RAngleLoc);
+  if (Type.isInvalid())
+    return true;
+  
+  if (Id.getKind() == UnqualifiedId::IK_ConstructorName)
+    Id.setConstructorName(Type.get(), NameLoc, RAngleLoc);
+  else
+    Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc);
+  
+  return false;
+}
+
+/// \brief Parse a C++ unqualified-id (or a C identifier), which describes the
+/// name of an entity.
+///
+/// \code
+///       unqualified-id: [C++ expr.prim.general]
+///         identifier
+///         operator-function-id
+///         conversion-function-id
+/// [C++0x] literal-operator-id [TODO]
+///         ~ class-name
+///         template-id
+///
+///       operator-function-id: [C++ 13.5]
+///         'operator' operator
+///
+/// operator: one of
+///            new   delete  new[]   delete[]
+///            +     -    *  /    %  ^    &   |   ~
+///            !     =    <  >    += -=   *=  /=  %=
+///            ^=    &=   |= <<   >> >>= <<=  ==  !=
+///            <=    >=   && ||   ++ --   ,   ->* ->
+///            ()    []
+///
+///       conversion-function-id: [C++ 12.3.2]
+///         operator conversion-type-id
+///
+///       conversion-type-id:
+///         type-specifier-seq conversion-declarator[opt]
+///
+///       conversion-declarator:
+///         ptr-operator conversion-declarator[opt]
+/// \endcode
+///
+/// \param The nested-name-specifier that preceded this unqualified-id. If
+/// non-empty, then we are parsing the unqualified-id of a qualified-id.
+///
+/// \param EnteringContext whether we are entering the scope of the 
+/// nested-name-specifier.
+///
+/// \param AllowDestructorName whether we allow parsing of a destructor name.
+///
+/// \param AllowConstructorName whether we allow parsing a constructor name.
+///
+/// \param Result on a successful parse, contains the parsed unqualified-id.
+///
+/// \returns true if parsing fails, false otherwise.
+bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
+                                bool AllowDestructorName,
+                                bool AllowConstructorName,
+                                UnqualifiedId &Result) {
+  // unqualified-id:
+  //   identifier
+  //   template-id (when it hasn't already been annotated)
+  if (Tok.is(tok::identifier)) {
+    // Consume the identifier.
+    IdentifierInfo *Id = Tok.getIdentifierInfo();
+    SourceLocation IdLoc = ConsumeToken();
+
+    if (AllowConstructorName && 
+        Actions.isCurrentClassName(*Id, CurScope, &SS)) {
+      // We have parsed a constructor name.
+      Result.setConstructorName(Actions.getTypeName(*Id, IdLoc, CurScope,
+                                                    &SS, false),
+                                IdLoc, IdLoc);
+    } else {
+      // We have parsed an identifier.
+      Result.setIdentifier(Id, IdLoc);      
+    }
+
+    // If the next token is a '<', we may have a template.
+    if (Tok.is(tok::less))
+      return ParseUnqualifiedIdTemplateId(SS, Id, IdLoc, EnteringContext, 
+                                          Result);
+    
+    return false;
+  }
+  
+  // unqualified-id:
+  //   template-id (already parsed and annotated)
+  if (Tok.is(tok::annot_template_id)) {
+    // FIXME: Could this be a constructor name???
+    
+    // We have already parsed a template-id; consume the annotation token as
+    // our unqualified-id.
+    Result.setTemplateId(
+                  static_cast<TemplateIdAnnotation*>(Tok.getAnnotationValue()));
+    ConsumeToken();
+    return false;
+  }
+  
+  // unqualified-id:
+  //   operator-function-id
+  //   conversion-function-id
+  if (Tok.is(tok::kw_operator)) {
+    // Consume the 'operator' keyword.
+    SourceLocation KeywordLoc = ConsumeToken();
+
+    // Determine what kind of operator name we have.
+    unsigned SymbolIdx = 0;
+    SourceLocation SymbolLocations[3];
+    OverloadedOperatorKind Op = OO_None;
+    switch (Tok.getKind()) {
+      case tok::kw_new:
+      case tok::kw_delete: {
+        bool isNew = Tok.getKind() == tok::kw_new;
+        // Consume the 'new' or 'delete'.
+        SymbolLocations[SymbolIdx++] = ConsumeToken();
+        if (Tok.is(tok::l_square)) {
+          // Consume the '['.
+          SourceLocation LBracketLoc = ConsumeBracket();
+          // Consume the ']'.
+          SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
+                                                           LBracketLoc);
+          if (RBracketLoc.isInvalid())
+            return true;
+          
+          SymbolLocations[SymbolIdx++] = LBracketLoc;
+          SymbolLocations[SymbolIdx++] = RBracketLoc;
+          Op = isNew? OO_Array_New : OO_Array_Delete;
+        } else {
+          Op = isNew? OO_New : OO_Delete;
+        }
+        break;
+      }
+        
+  #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
+      case tok::Token:                                                     \
+        SymbolLocations[SymbolIdx++] = ConsumeToken();                     \
+        Op = OO_##Name;                                                    \
+        break;
+  #define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
+  #include "clang/Basic/OperatorKinds.def"
+        
+      case tok::l_paren: {
+        // Consume the '('.
+        SourceLocation LParenLoc = ConsumeParen();
+        // Consume the ')'.
+        SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren,
+                                                       LParenLoc);
+        if (RParenLoc.isInvalid())
+          return true;
+
+        SymbolLocations[SymbolIdx++] = LParenLoc;
+        SymbolLocations[SymbolIdx++] = RParenLoc;
+        Op = OO_Call;
+        break;
+      }
+        
+      case tok::l_square: {
+        // Consume the '['.
+        SourceLocation LBracketLoc = ConsumeBracket();
+        // Consume the ']'.
+        SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
+                                                         LBracketLoc);
+        if (RBracketLoc.isInvalid())
+          return true;
+        
+        SymbolLocations[SymbolIdx++] = LBracketLoc;
+        SymbolLocations[SymbolIdx++] = RBracketLoc;
+        Op = OO_Subscript;
+        break;
+      }
+        
+      case tok::code_completion: {
+        // Code completion for the operator name.
+        Actions.CodeCompleteOperatorName(CurScope);
+        
+        // Consume the operator token.
+        ConsumeToken();
+        
+        // Don't try to parse any further.
+        return true;
+      }
+
+      default:
+        break;
+    }
+    
+    if (Op != OO_None) {
+      // We have parsed an operator-function-id.
+      Result.setOperatorFunctionId(KeywordLoc, Op, SymbolLocations);
+      
+      // If the next token is a '<', we may have a template.
+      if (Tok.is(tok::less))
+        return ParseUnqualifiedIdTemplateId(SS, 0, SourceLocation(), 
+                                            EnteringContext, Result);
+
+      return false;
+    }
+    
+    // Parse a conversion-function-id.
+    //
+    //   conversion-function-id: [C++ 12.3.2]
+    //     operator conversion-type-id
+    //
+    //   conversion-type-id:
+    //     type-specifier-seq conversion-declarator[opt]
+    //
+    //   conversion-declarator:
+    //     ptr-operator conversion-declarator[opt]
+    
+    // Parse the type-specifier-seq.
+    DeclSpec DS;
+    if (ParseCXXTypeSpecifierSeq(DS))
+      return true;
+    
+    // Parse the conversion-declarator, which is merely a sequence of
+    // ptr-operators.
+    Declarator D(DS, Declarator::TypeNameContext);
+    ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
+    
+    // Finish up the type.
+    Action::TypeResult Ty = Actions.ActOnTypeName(CurScope, D);
+    if (Ty.isInvalid())
+      return true;
+    
+    // Note that this is a conversion-function-id.
+    Result.setConversionFunctionId(KeywordLoc, Ty.get(), 
+                                   D.getSourceRange().getEnd());
+    return false;
+  }
+  
+  if ((AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) {
+    // C++ [expr.unary.op]p10:
+    //   There is an ambiguity in the unary-expression ~X(), where X is a 
+    //   class-name. The ambiguity is resolved in favor of treating ~ as a 
+    //    unary complement rather than treating ~X as referring to a destructor.
+    
+    // Parse the '~'.
+    SourceLocation TildeLoc = ConsumeToken();
+    
+    // Parse the class-name.
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok, diag::err_destructor_class_name);
+      return true;
+    }
+
+    // Parse the class-name (or template-name in a simple-template-id).
+    IdentifierInfo *ClassName = Tok.getIdentifierInfo();
+    SourceLocation ClassNameLoc = ConsumeToken();
+    
+    // Note that this is a destructor name.
+    Action::TypeTy *Ty = Actions.getTypeName(*ClassName, ClassNameLoc,
+                                             CurScope, &SS);
+    if (!Ty) {
+      Diag(ClassNameLoc, diag::err_destructor_class_name);
+      return true;
+    }
+    
+    Result.setDestructorName(TildeLoc, Ty, ClassNameLoc);
+    
+    if (Tok.is(tok::less))
+      return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc,
+                                          EnteringContext, Result);
+
+    return false;
+  }
+  
+  Diag(Tok, diag::err_expected_unqualified_id);
+  return true;
+}
+
 /// TryParseOperatorFunctionId - Attempts to parse a C++ overloaded
 /// operator name (C++ [over.oper]). If successful, returns the
 /// predefined identifier that corresponds to that overloaded

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=85851&r1=85850&r2=85851&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Nov  2 19:35:08 2009
@@ -1606,45 +1606,48 @@
 /// GetNameForDeclarator - Determine the full declaration name for the
 /// given Declarator.
 DeclarationName Sema::GetNameForDeclarator(Declarator &D) {
-  switch (D.getKind()) {
-  case Declarator::DK_Abstract:
-    assert(D.getIdentifier() == 0 && "abstract declarators have no name");
-    return DeclarationName();
+  UnqualifiedId &Name = D.getName();
+  switch (Name.getKind()) {
+  case UnqualifiedId::IK_Identifier:
+    return DeclarationName(Name.Identifier);
 
-  case Declarator::DK_Normal:
-    assert (D.getIdentifier() != 0 && "normal declarators have an identifier");
-    return DeclarationName(D.getIdentifier());
+  case UnqualifiedId::IK_OperatorFunctionId:
+    return Context.DeclarationNames.getCXXOperatorName(
+                                              Name.OperatorFunctionId.Operator);
 
-  case Declarator::DK_Constructor: {
-    QualType Ty = GetTypeFromParser(D.getDeclaratorIdType());
+  case UnqualifiedId::IK_ConversionFunctionId: {
+    QualType Ty = GetTypeFromParser(Name.ConversionFunctionId);
+    if (Ty.isNull())
+      return DeclarationName();
+    
+    return Context.DeclarationNames.getCXXConversionFunctionName(
+                                                  Context.getCanonicalType(Ty));
+  }
+      
+  case UnqualifiedId::IK_ConstructorName: {
+    QualType Ty = GetTypeFromParser(Name.ConstructorName);
+    if (Ty.isNull())
+      return DeclarationName();
+    
     return Context.DeclarationNames.getCXXConstructorName(
                                                 Context.getCanonicalType(Ty));
   }
-
-  case Declarator::DK_Destructor: {
-    QualType Ty = GetTypeFromParser(D.getDeclaratorIdType());
+      
+  case UnqualifiedId::IK_DestructorName: {
+    QualType Ty = GetTypeFromParser(Name.DestructorName);
+    if (Ty.isNull())
+      return DeclarationName();
+    
     return Context.DeclarationNames.getCXXDestructorName(
                                                 Context.getCanonicalType(Ty));
   }
-
-  case Declarator::DK_Conversion: {
-    // FIXME: We'd like to keep the non-canonical type for diagnostics!
-    QualType Ty = GetTypeFromParser(D.getDeclaratorIdType());
-    return Context.DeclarationNames.getCXXConversionFunctionName(
-                                                Context.getCanonicalType(Ty));
-  }
-
-  case Declarator::DK_Operator:
-    assert(D.getIdentifier() == 0 && "operator names have no identifier");
-    return Context.DeclarationNames.getCXXOperatorName(
-                                                D.getOverloadedOperator());
       
-  case Declarator::DK_TemplateId: {
-    TemplateName Name
-      = TemplateName::getFromVoidPointer(D.getTemplateId()->Template);    
-    if (TemplateDecl *Template = Name.getAsTemplateDecl())
+  case UnqualifiedId::IK_TemplateId: {
+    TemplateName TName
+      = TemplateName::getFromVoidPointer(Name.TemplateId->Template);    
+    if (TemplateDecl *Template = TName.getAsTemplateDecl())
       return Template->getDeclName();
-    if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl())
+    if (OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl())
       return Ovl->getDeclName();
     
     return DeclarationName();
@@ -2517,7 +2520,7 @@
     isInline |= IsFunctionDefinition;
   }
 
-  if (D.getKind() == Declarator::DK_Constructor) {
+  if (Name.getNameKind() == DeclarationName::CXXConstructorName) {
     // This is a C++ constructor declaration.
     assert(DC->isRecord() &&
            "Constructors can only be declared in a member context");
@@ -2530,7 +2533,7 @@
                                        D.getIdentifierLoc(), Name, R, DInfo,
                                        isExplicit, isInline,
                                        /*isImplicitlyDeclared=*/false);
-  } else if (D.getKind() == Declarator::DK_Destructor) {
+  } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
     // This is a C++ destructor declaration.
     if (DC->isRecord()) {
       R = CheckDestructorDeclarator(D, SC);
@@ -2552,7 +2555,7 @@
                                    /*hasPrototype=*/true);
       D.setInvalidType();
     }
-  } else if (D.getKind() == Declarator::DK_Conversion) {
+  } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
     if (!DC->isRecord()) {
       Diag(D.getIdentifierLoc(),
            diag::err_conv_function_not_member);
@@ -2798,8 +2801,8 @@
   bool HasExplicitTemplateArgs = false;
   llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
   SourceLocation LAngleLoc, RAngleLoc;
-  if (D.getKind() == Declarator::DK_TemplateId) {
-    TemplateIdAnnotation *TemplateId = D.getTemplateId();
+  if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+    TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
     ASTTemplateArgsPtr TemplateArgsPtr(*this,
                                        TemplateId->getTemplateArgs(),
                                        TemplateId->getTemplateArgIsType(),

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=85851&r1=85850&r2=85851&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Nov  2 19:35:08 2009
@@ -2295,7 +2295,7 @@
   //   (7.1.3); however, a typedef-name that names a class shall not
   //   be used as the identifier in the declarator for a destructor
   //   declaration.
-  QualType DeclaratorType = GetTypeFromParser(D.getDeclaratorIdType());
+  QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName);
   if (isa<TypedefType>(DeclaratorType)) {
     Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
       << DeclaratorType;
@@ -2421,7 +2421,7 @@
   // C++ [class.conv.fct]p4:
   //   The conversion-type-id shall not represent a function type nor
   //   an array type.
-  QualType ConvType = GetTypeFromParser(D.getDeclaratorIdType());
+  QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId);
   if (ConvType->isArrayType()) {
     Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array);
     ConvType = Context.getPointerType(ConvType);
@@ -4515,12 +4515,12 @@
 
   if (DC->isFileContext()) {
     // This implies that it has to be an operator or function.
-    if (D.getKind() == Declarator::DK_Constructor ||
-        D.getKind() == Declarator::DK_Destructor ||
-        D.getKind() == Declarator::DK_Conversion) {
+    if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ||
+        D.getName().getKind() == UnqualifiedId::IK_DestructorName ||
+        D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) {
       Diag(Loc, diag::err_introducing_special_friend) <<
-        (D.getKind() == Declarator::DK_Constructor ? 0 :
-         D.getKind() == Declarator::DK_Destructor ? 1 : 2);
+        (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 :
+         D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2);
       return DeclPtrTy();
     }
   }

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=85851&r1=85850&r2=85851&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Nov  2 19:35:08 2009
@@ -4043,8 +4043,8 @@
   // argument list into our AST format.
   bool HasExplicitTemplateArgs = false;
   llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
-  if (D.getKind() == Declarator::DK_TemplateId) {
-    TemplateIdAnnotation *TemplateId = D.getTemplateId();
+  if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) {
+    TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
     ASTTemplateArgsPtr TemplateArgsPtr(*this,
                                        TemplateId->getTemplateArgs(),
                                        TemplateId->getTemplateArgIsType(),
@@ -4147,7 +4147,7 @@
   //
   // C++98 has the same restriction, just worded differently.
   FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();
-  if (D.getKind() != Declarator::DK_TemplateId && !FunTmpl &&
+  if (D.getName().getKind() != UnqualifiedId::IK_TemplateId && !FunTmpl &&
       D.getCXXScopeSpec().isSet() && 
       !ScopeSpecifierHasTemplateId(D.getCXXScopeSpec()))
     Diag(D.getIdentifierLoc(), 

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=85851&r1=85850&r2=85851&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Mon Nov  2 19:35:08 2009
@@ -870,6 +870,11 @@
 
 QualType Sema::GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo) {
   QualType QT = QualType::getFromOpaquePtr(Ty);
+  if (QT.isNull()) {
+    if (DInfo) *DInfo = 0;
+    return QualType();
+  }
+
   DeclaratorInfo *DI = 0;
   if (LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) {
     QT = LIT->getType();
@@ -893,20 +898,19 @@
   // have a type.
   QualType T;
 
-  switch (D.getKind()) {
-  case Declarator::DK_Abstract:
-  case Declarator::DK_Normal:
-  case Declarator::DK_Operator:
-  case Declarator::DK_TemplateId:
+  switch (D.getName().getKind()) {
+  case UnqualifiedId::IK_Identifier:
+  case UnqualifiedId::IK_OperatorFunctionId:
+  case UnqualifiedId::IK_TemplateId:
     T = ConvertDeclSpecToType(D, *this);
     
     if (!D.isInvalidType() && OwnedDecl && D.getDeclSpec().isTypeSpecOwned())
       *OwnedDecl = cast<TagDecl>((Decl *)D.getDeclSpec().getTypeRep());
     break;
 
-  case Declarator::DK_Constructor:
-  case Declarator::DK_Destructor:
-  case Declarator::DK_Conversion:
+  case UnqualifiedId::IK_ConstructorName:
+  case UnqualifiedId::IK_DestructorName:
+  case UnqualifiedId::IK_ConversionFunctionId:
     // Constructors and destructors don't have return types. Use
     // "void" instead. Conversion operators will check their return
     // types separately.

Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp?rev=85851&r1=85850&r2=85851&view=diff

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp Mon Nov  2 19:35:08 2009
@@ -13,9 +13,9 @@
 
 // FIXME: Repeated diagnostics here!
 template void X0::f0<int>(int); // expected-error 2{{incomplete type}} \
-  // expected-error{{invalid token after}}
+  // expected-error{{does not refer}}
 template void X1<int>::f0<int>(int); // expected-error 2{{implicit instantiation of undefined template}} \
-  // expected-error{{invalid token}}
+  // expected-error{{does not refer}}
 
 // A definition of a class template or class member template shall be in scope 
 // at the point of the explicit instantiation of the class template or class 

Modified: cfe/trunk/test/SemaCXX/constructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constructor.cpp?rev=85851&r1=85850&r2=85851&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/constructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/constructor.cpp Mon Nov  2 19:35:08 2009
@@ -14,7 +14,7 @@
   static Foo(short, short); // expected-error{{constructor cannot be declared 'static'}}
   virtual Foo(double); // expected-error{{constructor cannot be declared 'virtual'}}
   Foo(long) const; // expected-error{{'const' qualifier is not allowed on a constructor}}
-
+  
   int Foo(int, int); // expected-error{{constructor cannot have a return type}}
 };
 

Modified: cfe/trunk/test/SemaTemplate/constructor-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/constructor-template.cpp?rev=85851&r1=85850&r2=85851&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/constructor-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/constructor-template.cpp Mon Nov  2 19:35:08 2009
@@ -51,3 +51,4 @@
 template<class C> struct A {};
 template <> struct A<int>{A(const A<int>&);};
 struct B { A<int> x; B(B& a) : x(a.x) {} };
+





More information about the cfe-commits mailing list