]> granicus.if.org Git - clang/commitdiff
Eliminate all of the placeholder identifiers used for constructors,
authorDouglas Gregor <dgregor@apple.com>
Mon, 17 Nov 2008 22:58:34 +0000 (22:58 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 17 Nov 2008 22:58:34 +0000 (22:58 +0000)
destructors, and conversion functions. The placeholders were used to
work around the fact that the parser and some of Sema really wanted
declarators to have simple identifiers; now, the code that deals with
declarators will use DeclarationNames.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59469 91177308-0d34-0410-b5e6-96231b3b80d8

18 files changed:
include/clang/AST/Decl.h
include/clang/AST/DeclCXX.h
include/clang/AST/DeclarationName.h
include/clang/Basic/DiagnosticKinds.def
include/clang/Basic/IdentifierTable.h
include/clang/Parse/DeclSpec.h
lib/AST/Decl.cpp
lib/AST/DeclCXX.cpp
lib/AST/DeclarationName.cpp
lib/Basic/IdentifierTable.cpp
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/Parser.cpp
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/conversion-function.cpp
test/SemaCXX/overloaded-operator-decl.cpp

index 2ac94a9bdfa4d1a1ac69938da8c98a2d7fc84f44..8e688fec5d984fd74387602bdc8815a5c3d5e989 100644 (file)
@@ -100,7 +100,7 @@ public:
   /// expensive string manipulation, so it should be called only when
   /// absolutely critical. For simple declarations, @c
   /// getIdentifierName() should suffice.
-  std::string getName() const;
+  std::string getName() const { return Name.getAsString(); }
   
   static bool classof(const Decl *D) {
     return D->getKind() >= NamedFirst && D->getKind() <= NamedLast;
@@ -558,7 +558,7 @@ protected:
 
 public:
   static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
-                              IdentifierInfo *Id, QualType T, 
+                              DeclarationName N, QualType T, 
                               StorageClass S = None, bool isInline = false, 
                               ScopedDecl *PrevDecl = 0,
                               SourceLocation TSStartLoc = SourceLocation());  
index 8edfc650a4abd507b5eba7d04d1dd1ee8754eb00..86cd68ac8e8ec086fd8be42e4716da892461f4d9 100644 (file)
@@ -58,6 +58,11 @@ public:
             isa<CXXConversionDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&
            "Overloaded functions must have the same name");
     Functions.push_back(FD);
+
+    // An overloaded function declaration always has the location of
+    // the most-recently-added function declaration.
+    if (FD->getLocation().isValid())
+      this->setLocation(FD->getLocation());
   }
 
   function_iterator function_begin() { return Functions.begin(); }
@@ -396,7 +401,7 @@ protected:
 
 public:
   static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
-                              SourceLocation L, IdentifierInfo *Id,
+                              SourceLocation L, DeclarationName N,
                               QualType T, bool isStatic = false,
                               bool isInline = false,  ScopedDecl *PrevDecl = 0);
   
index 909255c349524123bdea44595c82f73231405b45..877d23566bc170f0bb5148db1ea763e4709ca087 100644 (file)
@@ -164,6 +164,9 @@ public:
   /// getNameKind - Determine what kind of name this is.
   NameKind getNameKind() const;
 
+  /// getName - Retrieve the human-readable string for this name.
+  std::string getAsString() const;
+
   /// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in
   /// this declaration name, or NULL if this declaration name isn't a
   /// simple identifier.
index c232eaa449c35037a7da7f5ef7cf79618df9b995..d427e69ac7724a169f9f9716804e3ec87533347f 100644 (file)
@@ -660,6 +660,8 @@ DIAG(ext_anon_param_requires_type_specifier, EXTENSION,
      "type specifier required for unnamed parameter, defaults to int")
 DIAG(err_missing_param, ERROR,
      "expected parameter declarator")
+DIAG(err_bad_variable_name, ERROR,
+     "'%0' cannot be the name of a variable or data member")
 
 DIAG(err_declarator_need_ident, ERROR,
      "declarator requires an identifier")
index a13d4ba538c1a49df12bca8c5eafcfc6404f1467..58ad133e3bac13bff3bb3bb676118e80645ca2ea 100644 (file)
@@ -179,16 +179,6 @@ class IdentifierTable {
   /// overloadable operators in C++.
   IdentifierInfo *OverloadedOperators[NUM_OVERLOADED_OPERATORS];
 
-  /// ConstructorId - Placeholder identifier for C++ constructors.
-  IdentifierInfo *ConstructorId;
-
-  /// DestructorId - Placeholder identifier for C++ destructor.
-  IdentifierInfo *DestructorId;
-
-  /// ConversionFunctionId - Placeholder identifier for a C++
-  /// conversion function.
-  IdentifierInfo *ConversionFunctionId;
-
 public:
   /// IdentifierTable ctor - Create the identifier table, populating it with
   /// info about the language keywords for the language specified by LangOpts.
@@ -214,18 +204,6 @@ public:
     return *OverloadedOperators[Op];
   }
 
-  /// getConstructorId - Return a placeholder identifier for a C++
-  /// constructor.
-  IdentifierInfo &getConstructorId();
-
-  /// getDestructorId - Return a placeholder identifier for a C++
-  /// destructor.
-  IdentifierInfo &getDestructorId();
-
-  /// getConversionFunctionId - Return a placeholder identifier for a
-  /// C++ conversion function.
-  IdentifierInfo &getConversionFunctionId();
-
   typedef HashTableTy::const_iterator iterator;
   typedef HashTableTy::const_iterator const_iterator;
   
index d1b887ff3028760baf14480d3e571d9853cd35c3..46629637bc355a087c99ea3a862ca9a0ee7da3b3 100644 (file)
@@ -767,7 +767,12 @@ public:
   /// isPastIdentifier - Return true if we have parsed beyond the point where
   /// the
   bool isPastIdentifier() const { return IdentifierLoc.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; }
   
@@ -780,31 +785,26 @@ public:
       Kind = DK_Abstract;
   }
   
-  /// SetConstructor - Set this declarator to be a C++ constructor
+  /// setConstructor - Set this declarator to be a C++ constructor
   /// declarator.
-  void SetConstructor(Action::TypeTy *Ty, IdentifierInfo *ID, 
-                      SourceLocation Loc) {
-    Identifier = ID;
+  void setConstructor(Action::TypeTy *Ty, SourceLocation Loc) {
     IdentifierLoc = Loc;
     Kind = DK_Constructor;
     Type = Ty;
   }
 
-  /// SetDestructor - Set this declarator to be a C++ destructor
+  /// setDestructor - Set this declarator to be a C++ destructor
   /// declarator.
-  void SetDestructor(Action::TypeTy *Ty, IdentifierInfo *ID, 
-                     SourceLocation Loc) {
-    Identifier = ID;
+  void setDestructor(Action::TypeTy *Ty, SourceLocation Loc) {
     IdentifierLoc = Loc;
     Kind = DK_Destructor;
     Type = Ty;
   }
 
-  // SetConversionFunction - Set this declarator to be a C++
+  // setConversionFunction - Set this declarator to be a C++
   // conversion function declarator.
-  void SetConversionFunction(Action::TypeTy *Ty, IdentifierInfo *ID, 
-                             SourceLocation Loc) {
-    Identifier = ID;
+  void setConversionFunction(Action::TypeTy *Ty, SourceLocation Loc) {
+    Identifier = 0;
     IdentifierLoc = Loc;
     Kind = DK_Conversion;
     Type = Ty;
index dc4d6027ee8b60ea4b67bee7f9095ee84bf1c239..eee934bebba229bcae25f0df4bd35695ba47ce76 100644 (file)
@@ -67,12 +67,12 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
 
 FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
                                    SourceLocation L, 
-                                   IdentifierInfo *Id, QualType T, 
+                                   DeclarationName N, QualType T, 
                                    StorageClass S, bool isInline, 
                                    ScopedDecl *PrevDecl,
                                    SourceLocation TypeSpecStartLoc) {
   void *Mem = C.getAllocator().Allocate<FunctionDecl>();
-  return new (Mem) FunctionDecl(Function, DC, L, Id, T, S, isInline, PrevDecl,
+  return new (Mem) FunctionDecl(Function, DC, L, N, T, S, isInline, PrevDecl,
                                 TypeSpecStartLoc);
 }
 
@@ -129,54 +129,6 @@ FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C,
   return new (Mem) FileScopeAsmDecl(L, Str);
 }
 
-//===----------------------------------------------------------------------===//
-// NamedDecl Implementation
-//===----------------------------------------------------------------------===//
-
-std::string NamedDecl::getName() const {
-  switch (Name.getNameKind()) {
-  case DeclarationName::Identifier:
-    if (const IdentifierInfo *II = Name.getAsIdentifierInfo())
-      return II->getName();
-    return "";
-
-  case DeclarationName::ObjCZeroArgSelector:
-  case DeclarationName::ObjCOneArgSelector:
-  case DeclarationName::ObjCMultiArgSelector:
-    return Name.getObjCSelector().getName();
-
-  case DeclarationName::CXXConstructorName: {
-    QualType ClassType = Name.getCXXNameType();
-    if (const RecordType *ClassRec = ClassType->getAsRecordType())
-      return ClassRec->getDecl()->getName();
-    return ClassType.getAsString();
-  }
-
-  case DeclarationName::CXXDestructorName: {
-    std::string Result = "~";
-    QualType Type = Name.getCXXNameType();
-    if (const RecordType *Rec = Type->getAsRecordType())
-      Result += Rec->getDecl()->getName();
-    else
-      Result += Type.getAsString();
-    return Result;
-  }
-
-  case DeclarationName::CXXConversionFunctionName: {
-    std::string Result = "operator ";
-    QualType Type = Name.getCXXNameType();
-    if (const RecordType *Rec = Type->getAsRecordType())
-      Result += Rec->getDecl()->getName();
-    else
-      Result += Type.getAsString();
-    return Result;
-  }
-  }
-
-  assert(false && "Unexpected declaration name kind");
-  return "";
-}
-
 //===----------------------------------------------------------------------===//
 // ScopedDecl Implementation
 //===----------------------------------------------------------------------===//
index 8855e99a26f2147be2041063df7613afcff8a2db..4037404124d323c6ef13f30646b123139734e1d8 100644 (file)
@@ -123,11 +123,12 @@ void CXXRecordDecl::addConversionFunction(ASTContext &Context,
 
 CXXMethodDecl *
 CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
-                      SourceLocation L, IdentifierInfo *Id,
+                      SourceLocation L, DeclarationName N,
                       QualType T, bool isStatic, bool isInline,
                       ScopedDecl *PrevDecl) {
   void *Mem = C.getAllocator().Allocate<CXXMethodDecl>();
-  return new (Mem) CXXMethodDecl(CXXMethod, RD, L, Id, T, isStatic, isInline, PrevDecl);
+  return new (Mem) CXXMethodDecl(CXXMethod, RD, L, N, T, isStatic, isInline, 
+                                 PrevDecl);
 }
 
 QualType CXXMethodDecl::getThisType(ASTContext &C) const {
index 4266ef5eaf82fa58048458002567fbfd82d9ccc2..d58016a44cc772a446e9e51fde3054d805f8b8e5 100644 (file)
@@ -12,6 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 #include "clang/AST/DeclarationName.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/Decl.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/Bitcode/Serialize.h"
@@ -94,6 +96,50 @@ DeclarationName::NameKind DeclarationName::getNameKind() const {
   return Identifier;
 }
 
+std::string DeclarationName::getAsString() const {
+  switch (getNameKind()) {
+  case Identifier:
+    if (const IdentifierInfo *II = getAsIdentifierInfo())
+      return II->getName();
+    return "";
+
+  case ObjCZeroArgSelector:
+  case ObjCOneArgSelector:
+  case ObjCMultiArgSelector:
+    return getObjCSelector().getName();
+
+  case CXXConstructorName: {
+    QualType ClassType = getCXXNameType();
+    if (const RecordType *ClassRec = ClassType->getAsRecordType())
+      return ClassRec->getDecl()->getName();
+    return ClassType.getAsString();
+  }
+
+  case CXXDestructorName: {
+    std::string Result = "~";
+    QualType Type = getCXXNameType();
+    if (const RecordType *Rec = Type->getAsRecordType())
+      Result += Rec->getDecl()->getName();
+    else
+      Result += Type.getAsString();
+    return Result;
+  }
+
+  case CXXConversionFunctionName: {
+    std::string Result = "operator ";
+    QualType Type = getCXXNameType();
+    if (const RecordType *Rec = Type->getAsRecordType())
+      Result += Rec->getDecl()->getName();
+    else
+      Result += Type.getAsString();
+    return Result;
+  }
+  }
+
+  assert(false && "Unexpected declaration name kind");
+  return "";
+}
+
 QualType DeclarationName::getCXXNameType() const {
   if (CXXSpecialName *CXXName = getAsCXXSpecialName())
     return CXXName->Type;
index b83266d1ff8c106aee0206a8f459d90dbfa6adce..38bdb7e630c3b9e848db1e47fea5d3e0f27c82d2 100644 (file)
@@ -42,8 +42,7 @@ IdentifierInfo::IdentifierInfo() {
 
 IdentifierTable::IdentifierTable(const LangOptions &LangOpts)
   // Start with space for 8K identifiers.
-  : HashTable(8192), 
-    ConstructorId(0), DestructorId(0), ConversionFunctionId(0) {
+  : HashTable(8192) {
 
   // Populate the identifier table with info about keywords for the current
   // language.
@@ -53,32 +52,7 @@ IdentifierTable::IdentifierTable(const LangOptions &LangOpts)
 
 // This cstor is intended to be used only for serialization.
 IdentifierTable::IdentifierTable() 
-  : HashTable(8192), 
-    ConstructorId(0), DestructorId(0), ConversionFunctionId(0) { }
-
-/// getConstructorId - Return a placeholder identifier for a C++
-/// constructor.
-IdentifierInfo &IdentifierTable::getConstructorId() {
-  if (!ConstructorId)
-    ConstructorId = &get("<constructor>");
-  return *ConstructorId;
-}
-
-/// getDestructorId - Return a placeholder identifier for a C++
-/// destructor.
-IdentifierInfo &IdentifierTable::getDestructorId() {
-  if (!DestructorId)
-    DestructorId = &get("<destructor>");
-  return *DestructorId;
-}
-
-/// getConversionFunctionId - Return a placeholder identifier for a
-/// C++ conversion function.
-IdentifierInfo &IdentifierTable::getConversionFunctionId() {
-  if (!ConversionFunctionId)
-    ConversionFunctionId = &get("<conversion function>");
-  return *ConversionFunctionId;
-}
+  : HashTable(8192) { }
 
 //===----------------------------------------------------------------------===//
 // Language Keyword Implementation
index baa510485a5a89cb5f7448ade169e7801a361142..048fafbe2d359dee6f7e15a4b55a6f50d1773465 100644 (file)
@@ -1440,8 +1440,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
     // a normal identifier.
     if (getLang().CPlusPlus && 
         Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope))
-      D.SetConstructor(Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope),
-                       &PP.getIdentifierTable().getConstructorId(), 
+      D.setConstructor(Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope),
                        Tok.getLocation());
     else
       D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
@@ -1452,8 +1451,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
     SourceLocation TildeLoc = ConsumeToken();
     if (Tok.is(tok::identifier)) {
       if (TypeTy *Type = ParseClassName())
-        D.SetDestructor(Type, &PP.getIdentifierTable().getDestructorId(), 
-                        TildeLoc);
+        D.setDestructor(Type, TildeLoc);
       else
         D.SetIdentifier(0, TildeLoc);
     } else {
@@ -1469,9 +1467,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
     } else {
       // This must be a conversion function (C++ [class.conv.fct]).
       if (TypeTy *ConvType = ParseConversionFunctionId()) {
-        D.SetConversionFunction(ConvType, 
-                                &PP.getIdentifierTable().getConversionFunctionId(), 
-                                OperatorLoc);
+        D.setConversionFunction(ConvType, OperatorLoc);
       }
     }
   } else if (Tok.is(tok::l_paren) && SS.isEmpty()) {
index 752d552f11d1c760979590ecc0e238cf456003ca..48ced227238a651e81bf889076658d512893ad65 100644 (file)
@@ -454,7 +454,7 @@ Parser::DeclTy *Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
     // Parse the first declarator.
     ParseDeclarator(DeclaratorInfo);
     // Error parsing the declarator?
-    if (DeclaratorInfo.getIdentifier() == 0) {
+    if (!DeclaratorInfo.hasName()) {
       // If so, skip until the semi-colon or a }.
       SkipUntil(tok::r_brace, true);
       if (Tok.is(tok::semi))
index ee4cd7b554f39a6e9f21b14d7399f08177748059..3b36ebec7b954db465a1670f7a5905a3b7d1a15a 100644 (file)
@@ -424,7 +424,7 @@ Parser::DeclTy *Parser::ParseDeclarationOrFunctionDefinition() {
   Declarator DeclaratorInfo(DS, Declarator::FileContext);
   ParseDeclarator(DeclaratorInfo);
   // Error parsing the declarator?
-  if (DeclaratorInfo.getIdentifier() == 0) {
+  if (!DeclaratorInfo.hasName()) {
     // If so, skip until the semi-colon or a }.
     SkipUntil(tok::r_brace, true);
     if (Tok.is(tok::semi))
index 50a12f13855045dd4a58853e424ac3173b50fc14..771dc96463ad366b3db3df964be39cb0e379b371 100644 (file)
@@ -272,7 +272,8 @@ public:
   QualType ConvertDeclSpecToType(const DeclSpec &DS);
   void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);
   QualType GetTypeForDeclarator(Declarator &D, Scope *S);
-  
+  DeclarationName GetNameForDeclarator(Declarator &D);
+
   QualType ObjCGetTypeForMethodDefinition(DeclTy *D);
 
   bool UnwrapSimilarPointerTypes(QualType& T1, QualType& T2);
index ea2a3ad9a75d4bececca555ad2d85b568ecf85b7..9c0a40e74abe89d341bc83c779e0e4bfd2e50b9a 100644 (file)
@@ -754,14 +754,49 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
   return CheckInitList.HadError();
 }
 
+/// 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();
+
+  case Declarator::DK_Normal:
+    assert (D.getIdentifier() != 0 && "normal declarators have an identifier");
+    return DeclarationName(D.getIdentifier());
+
+  case Declarator::DK_Constructor: {
+    QualType Ty = Context.getTypeDeclType((TypeDecl *)D.getDeclaratorIdType());
+    Ty = Context.getCanonicalType(Ty);
+    return Context.DeclarationNames.getCXXConstructorName(Ty);
+  }
+
+  case Declarator::DK_Destructor: {
+    QualType Ty = Context.getTypeDeclType((TypeDecl *)D.getDeclaratorIdType());
+    Ty = Context.getCanonicalType(Ty);
+    return Context.DeclarationNames.getCXXDestructorName(Ty);
+  }
+
+  case Declarator::DK_Conversion: {
+    QualType Ty = QualType::getFromOpaquePtr(D.getDeclaratorIdType());
+    Ty = Context.getCanonicalType(Ty);
+    return Context.DeclarationNames.getCXXConversionFunctionName(Ty);
+  }
+  }
+
+  assert(false && "Unknown name kind");
+  return DeclarationName();
+}
+
 Sema::DeclTy *
 Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
   ScopedDecl *LastDeclarator = dyn_cast_or_null<ScopedDecl>((Decl *)lastDecl);
-  IdentifierInfo *II = D.getIdentifier();
-  
+  DeclarationName Name = GetNameForDeclarator(D);
+
   // All of these full declarators require an identifier.  If it doesn't have
   // one, the ParsedFreeStandingDeclSpec action should be used.
-  if (II == 0) {
+  if (!Name) {
     if (!D.getInvalidType())  // Reject this if we think it is valid.
       Diag(D.getDeclSpec().getSourceRange().getBegin(),
            diag::err_declarator_need_ident,
@@ -782,10 +817,10 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
   // See if this is a redefinition of a variable in the same scope.
   if (!D.getCXXScopeSpec().isSet()) {
     DC = CurContext;
-    PrevDecl = LookupDecl(II, Decl::IDNS_Ordinary, S);
+    PrevDecl = LookupDecl(Name, Decl::IDNS_Ordinary, S);
   } else { // Something like "int foo::x;"
     DC = static_cast<DeclContext*>(D.getCXXScopeSpec().getScopeRep());
-    PrevDecl = LookupDecl(II, Decl::IDNS_Ordinary, S, DC);
+    PrevDecl = LookupDecl(Name, Decl::IDNS_Ordinary, S, DC);
 
     // C++ 7.3.1.2p2:
     // Members (including explicit specializations of templates) of a named
@@ -798,16 +833,17 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
     if (PrevDecl == 0) {
       // No previous declaration in the qualifying scope.
       Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member,
-           II->getName(), D.getCXXScopeSpec().getRange());
+           Name.getAsString(), D.getCXXScopeSpec().getRange());
     } else if (!CurContext->Encloses(DC)) {
       // The qualifying scope doesn't enclose the original declaration.
       // Emit diagnostic based on current scope.
       SourceLocation L = D.getIdentifierLoc();
       SourceRange R = D.getCXXScopeSpec().getRange();
       if (isa<FunctionDecl>(CurContext)) {
-        Diag(L, diag::err_invalid_declarator_in_function, II->getName(), R);
+        Diag(L, diag::err_invalid_declarator_in_function, Name.getAsString(), 
+             R);
       } else {
-      Diag(L, diag::err_invalid_declarator_scope, II->getName(),
+      Diag(L, diag::err_invalid_declarator_scope, Name.getAsString(),
            cast<NamedDecl>(DC)->getName(), R);
       }
     }
@@ -878,13 +914,9 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
       bool isInvalidDecl = CheckConstructorDeclarator(D, R, SC);
 
       // Create the new declaration
-      QualType ClassType = Context.getTypeDeclType(cast<CXXRecordDecl>(DC));
-      ClassType = Context.getCanonicalType(ClassType);
-      DeclarationName ConName
-        = Context.DeclarationNames.getCXXConstructorName(ClassType);
       NewFD = CXXConstructorDecl::Create(Context, 
                                          cast<CXXRecordDecl>(DC),
-                                         D.getIdentifierLoc(), ConName, R,
+                                         D.getIdentifierLoc(), Name, R,
                                          isExplicit, isInline,
                                          /*isImplicitlyDeclared=*/false);
 
@@ -895,14 +927,9 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
       if (DC->isCXXRecord()) {
         bool isInvalidDecl = CheckDestructorDeclarator(D, R, SC);
 
-        QualType ClassType = Context.getTypeDeclType(cast<CXXRecordDecl>(DC));
-        ClassType = Context.getCanonicalType(ClassType);
-        DeclarationName DesName
-          = Context.DeclarationNames.getCXXDestructorName(ClassType);
-
         NewFD = CXXDestructorDecl::Create(Context,
                                           cast<CXXRecordDecl>(DC),
-                                          D.getIdentifierLoc(), DesName, R, 
+                                          D.getIdentifierLoc(), Name, R, 
                                           isInline,
                                           /*isImplicitlyDeclared=*/false);
 
@@ -913,7 +940,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
         // Create a FunctionDecl to satisfy the function definition parsing
         // code path.
         NewFD = FunctionDecl::Create(Context, DC, D.getIdentifierLoc(),
-                                     II, R, SC, isInline, LastDeclarator,
+                                     Name, R, SC, isInline, LastDeclarator,
                                      // FIXME: Move to DeclGroup...
                                    D.getDeclSpec().getSourceRange().getBegin());
         NewFD->setInvalidDecl();
@@ -926,14 +953,9 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
       } else {
         bool isInvalidDecl = CheckConversionDeclarator(D, R, SC);
 
-        QualType ConvType = R->getAsFunctionType()->getResultType();
-        ConvType = Context.getCanonicalType(ConvType);
-        DeclarationName ConvName
-          = Context.DeclarationNames.getCXXConversionFunctionName(ConvType);
-
         NewFD = CXXConversionDecl::Create(Context, 
                                           cast<CXXRecordDecl>(DC),
-                                          D.getIdentifierLoc(), ConvName, R,
+                                          D.getIdentifierLoc(), Name, R,
                                           isInline, isExplicit);
         
         if (isInvalidDecl)
@@ -942,13 +964,13 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
     } else if (DC->isCXXRecord()) {
       // This is a C++ method declaration.
       NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
-                                    D.getIdentifierLoc(), II, R,
+                                    D.getIdentifierLoc(), Name, R,
                                     (SC == FunctionDecl::Static), isInline,
                                     LastDeclarator);
     } else {
       NewFD = FunctionDecl::Create(Context, DC,
                                    D.getIdentifierLoc(),
-                                   II, R, SC, isInline, LastDeclarator,
+                                   Name, R, SC, isInline, LastDeclarator,
                                    // FIXME: Move to DeclGroup...
                                    D.getDeclSpec().getSourceRange().getBegin());
     }
@@ -1128,6 +1150,14 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
       Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember);
       InvalidDecl = true;
     }
+
+    IdentifierInfo *II = Name.getAsIdentifierInfo();
+    if (!II) {
+      Diag(D.getIdentifierLoc(), diag::err_bad_variable_name,
+           Name.getAsString());
+      return 0;
+    }
+
     if (DC->isCXXRecord()) {
       assert(SC == VarDecl::Static && "Invalid storage class for member!");
       // This is a static data member for a C++ class.
@@ -1184,7 +1214,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
   New->setLexicalDeclContext(CurContext);
 
   // If this has an identifier, add it to the scope stack.
-  if (II)
+  if (Name)
     PushOnScopeChains(New, S);
   // If any semantic error occurred, mark the decl as invalid.
   if (D.getInvalidType() || InvalidDecl)
index 2df6073e8b47fd7f377171396f88011358728cca..f601fe4dc6a9629209d94f526b7ab1f2eb57c58d 100644 (file)
@@ -421,7 +421,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
                                ExprTy *BW, ExprTy *InitExpr,
                                DeclTy *LastInGroup) {
   const DeclSpec &DS = D.getDeclSpec();
-  IdentifierInfo *II = D.getIdentifier();
+  DeclarationName Name = GetNameForDeclarator(D);
   Expr *BitWidth = static_cast<Expr*>(BW);
   Expr *Init = static_cast<Expr*>(InitExpr);
   SourceLocation Loc = D.getIdentifierLoc();
@@ -499,7 +499,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
 
   if (!Member) return LastInGroup;
 
-  assert((II || isInstField) && "No identifier for non-field ?");
+  assert((Name || isInstField) && "No identifier for non-field ?");
 
   // set/getAccess is not part of Decl's interface to avoid bloating it with C++
   // specific methods. Use a wrapper class that can be used with all C++ class
@@ -532,14 +532,14 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
       // FIXME: Emit diagnostic about only constructors taking base initializers
       // or something similar, when constructor support is in place.
       Diag(Loc, diag::err_not_bitfield_type,
-           II->getName(), BitWidth->getSourceRange());
+           Name.getAsString(), BitWidth->getSourceRange());
       InvalidDecl = true;
 
     } else if (isInstField) {
       // C++ 9.6p3: A bit-field shall have integral or enumeration type.
       if (!cast<FieldDecl>(Member)->getType()->isIntegralType()) {
         Diag(Loc, diag::err_not_integral_type_bitfield,
-             II->getName(), BitWidth->getSourceRange());
+             Name.getAsString(), BitWidth->getSourceRange());
         InvalidDecl = true;
       }
 
@@ -547,12 +547,12 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
       // A function typedef ("typedef int f(); f a;").
       // C++ 9.6p3: A bit-field shall have integral or enumeration type.
       Diag(Loc, diag::err_not_integral_type_bitfield,
-           II->getName(), BitWidth->getSourceRange());
+           Name.getAsString(), BitWidth->getSourceRange());
       InvalidDecl = true;
 
     } else if (isa<TypedefDecl>(Member)) {
       // "cannot declare 'A' to be a bit-field type"
-      Diag(Loc, diag::err_not_bitfield_type, II->getName(), 
+      Diag(Loc, diag::err_not_bitfield_type, Name.getAsString(), 
            BitWidth->getSourceRange());
       InvalidDecl = true;
 
@@ -561,7 +561,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
              "Didn't we cover all member kinds?");
       // C++ 9.6p3: A bit-field shall not be a static member.
       // "static member 'A' cannot be a bit-field"
-      Diag(Loc, diag::err_static_not_bitfield, II->getName(), 
+      Diag(Loc, diag::err_static_not_bitfield, Name.getAsString(), 
            BitWidth->getSourceRange());
       InvalidDecl = true;
     }
@@ -584,14 +584,14 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
       } else {
         // not const integral.
         Diag(Loc, diag::err_member_initialization,
-             II->getName(), Init->getSourceRange());
+             Name.getAsString(), Init->getSourceRange());
         InvalidDecl = true;
       }
 
     } else {
       // not static member.
       Diag(Loc, diag::err_member_initialization,
-           II->getName(), Init->getSourceRange());
+           Name.getAsString(), Init->getSourceRange());
       InvalidDecl = true;
     }
   }
index 6450387b02c1688b780f16c1b2342210ff482cbe..22ed411e64b3920df02ae20de3070cf5f4bcbc99 100644 (file)
@@ -15,6 +15,8 @@ public:
 
 operator int(); // expected-error{{conversion function must be a non-static member function}}
 
+operator int; // expected-error{{'operator int' cannot be the name of a variable or data member}}
+
 typedef int func_type(int);
 typedef int array_type[10];
 
index 8a042f68ef48b5d8eb23e206b9c26f4e1822e3d4..7b05c38274b1b5539b259826662d74b850b40f08 100644 (file)
@@ -20,7 +20,8 @@ void f(X x) {
   x = operator+(x, x);
 }
 
-X operator+(int, float); // expected-error{{overloaded 'operator+' must have at least one parameter of class or enumeration type}}
+X operator+(int, float); // expected-error{{overloaded 'operator+' must have at least one parameter of class or enumeration type}} \
+                         // expected-error{{previous definition is here}}
 
 X operator*(X, X = 5); // expected-error{{parameter of overloaded 'operator*' cannot have a default argument}}
 
@@ -35,3 +36,5 @@ typedef float FLOAT;
 Y& operator++(Y&);
 Y operator++(Y&, INT);
 X operator++(X&, FLOAT); // expected-error{{parameter of overloaded post-increment operator must have type 'int' (not 'float')}}
+
+int operator+; // expected-error{{redefinition of 'operator+' as different kind of symbol}}