aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Decl.h4
-rw-r--r--include/clang/AST/DeclCXX.h7
-rw-r--r--include/clang/AST/DeclarationName.h3
-rw-r--r--include/clang/Basic/DiagnosticKinds.def2
-rw-r--r--include/clang/Basic/IdentifierTable.h22
-rw-r--r--include/clang/Parse/DeclSpec.h26
-rw-r--r--lib/AST/Decl.cpp52
-rw-r--r--lib/AST/DeclCXX.cpp5
-rw-r--r--lib/AST/DeclarationName.cpp46
-rw-r--r--lib/Basic/IdentifierTable.cpp30
-rw-r--r--lib/Parse/ParseDecl.cpp10
-rw-r--r--lib/Parse/ParseDeclCXX.cpp2
-rw-r--r--lib/Parse/Parser.cpp2
-rw-r--r--lib/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaDecl.cpp88
-rw-r--r--lib/Sema/SemaDeclCXX.cpp18
-rw-r--r--test/SemaCXX/conversion-function.cpp2
-rw-r--r--test/SemaCXX/overloaded-operator-decl.cpp5
18 files changed, 160 insertions, 167 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 2ac94a9bdf..8e688fec5d 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -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());
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 8edfc650a4..86cd68ac8e 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -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);
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index 909255c349..877d23566b 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -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.
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index c232eaa449..d427e69ac7 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -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")
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h
index a13d4ba538..58ad133e3b 100644
--- a/include/clang/Basic/IdentifierTable.h
+++ b/include/clang/Basic/IdentifierTable.h
@@ -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;
diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h
index d1b887ff30..46629637bc 100644
--- a/include/clang/Parse/DeclSpec.h
+++ b/include/clang/Parse/DeclSpec.h
@@ -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;
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index dc4d6027ee..eee934bebb 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -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);
}
@@ -130,54 +130,6 @@ FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C,
}
//===----------------------------------------------------------------------===//
-// 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
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 8855e99a26..4037404124 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -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 {
diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp
index 4266ef5eaf..d58016a44c 100644
--- a/lib/AST/DeclarationName.cpp
+++ b/lib/AST/DeclarationName.cpp
@@ -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;
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index b83266d1ff..38bdb7e630 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -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
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index baa510485a..048fafbe2d 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -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()) {
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 752d552f11..48ced22723 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -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))
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index ee4cd7b554..3b36ebec7b 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -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))
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 50a12f1385..771dc96463 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -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);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index ea2a3ad9a7..9c0a40e74a 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -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)
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 2df6073e8b..f601fe4dc6 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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;
}
}
diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp
index 6450387b02..22ed411e64 100644
--- a/test/SemaCXX/conversion-function.cpp
+++ b/test/SemaCXX/conversion-function.cpp
@@ -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];
diff --git a/test/SemaCXX/overloaded-operator-decl.cpp b/test/SemaCXX/overloaded-operator-decl.cpp
index 8a042f68ef..7b05c38274 100644
--- a/test/SemaCXX/overloaded-operator-decl.cpp
+++ b/test/SemaCXX/overloaded-operator-decl.cpp
@@ -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}}