summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/DeclarationName.cpp39
-rw-r--r--clang/lib/Parse/MinimalAction.cpp2
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp14
-rw-r--r--clang/lib/Sema/IdentifierResolver.cpp51
-rw-r--r--clang/lib/Sema/IdentifierResolver.h27
-rw-r--r--clang/lib/Sema/Sema.h11
-rw-r--r--clang/lib/Sema/SemaCXXScopeSpec.cpp11
-rw-r--r--clang/lib/Sema/SemaChecking.cpp7
-rw-r--r--clang/lib/Sema/SemaDecl.cpp26
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp50
10 files changed, 173 insertions, 65 deletions
diff --git a/clang/lib/AST/DeclarationName.cpp b/clang/lib/AST/DeclarationName.cpp
index 96e194be8c9..4266ef5eaf8 100644
--- a/clang/lib/AST/DeclarationName.cpp
+++ b/clang/lib/AST/DeclarationName.cpp
@@ -25,8 +25,13 @@ namespace clang {
class CXXSpecialName
: public DeclarationNameExtra, public llvm::FoldingSetNode {
public:
+ /// Type - The type associated with this declaration name.
QualType Type;
+ /// FETokenInfo - Extra information associated with this declaration
+ /// name that can be used by the front end.
+ void *FETokenInfo;
+
void Profile(llvm::FoldingSetNodeID &ID) {
ID.AddInteger(ExtraKindOrNumArgs);
ID.AddPointer(Type.getAsOpaquePtr());
@@ -114,6 +119,39 @@ Selector DeclarationName::getObjCSelector() const {
return Selector();
}
+void *DeclarationName::getFETokenInfoAsVoid() const {
+ switch (getNameKind()) {
+ case Identifier:
+ return getAsIdentifierInfo()->getFETokenInfo<void>();
+
+ case CXXConstructorName:
+ case CXXDestructorName:
+ case CXXConversionFunctionName:
+ return getAsCXXSpecialName()->FETokenInfo;
+
+ default:
+ assert(false && "Declaration name has no FETokenInfo");
+ }
+ return 0;
+}
+
+void DeclarationName::setFETokenInfo(void *T) {
+ switch (getNameKind()) {
+ case Identifier:
+ getAsIdentifierInfo()->setFETokenInfo(T);
+ break;
+
+ case CXXConstructorName:
+ case CXXDestructorName:
+ case CXXConversionFunctionName:
+ getAsCXXSpecialName()->FETokenInfo = T;
+ break;
+
+ default:
+ assert(false && "Declaration name has no FETokenInfo");
+ }
+}
+
DeclarationNameTable::DeclarationNameTable() {
CXXSpecialNamesImpl = new llvm::FoldingSet<CXXSpecialName>;
}
@@ -159,6 +197,7 @@ DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
CXXSpecialName *SpecialName = new CXXSpecialName;
SpecialName->ExtraKindOrNumArgs = EKind;
SpecialName->Type = Ty;
+ SpecialName->FETokenInfo = 0;
SpecialNames->InsertNode(SpecialName, InsertPos);
return DeclarationName(SpecialName);
diff --git a/clang/lib/Parse/MinimalAction.cpp b/clang/lib/Parse/MinimalAction.cpp
index 58e391ee376..583781056e0 100644
--- a/clang/lib/Parse/MinimalAction.cpp
+++ b/clang/lib/Parse/MinimalAction.cpp
@@ -58,7 +58,7 @@ void MinimalAction::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
///
/// FIXME: Use the passed CXXScopeSpec for accurate C++ type checking.
Action::TypeTy *
-MinimalAction::isTypeName(const IdentifierInfo &II, Scope *S,
+MinimalAction::isTypeName(IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS) {
if (TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>())
if (TI->isTypeName)
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 8f14ce50b8d..19b521b2641 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -131,7 +131,7 @@ Parser::ExprResult Parser::ParseCXXIdExpression() {
// unqualified-id:
// identifier
// operator-function-id
- // conversion-function-id [TODO]
+ // conversion-function-id
// '~' class-name [TODO]
// template-id [TODO]
//
@@ -152,11 +152,15 @@ Parser::ExprResult Parser::ParseCXXIdExpression() {
if (IdentifierInfo *II = TryParseOperatorFunctionId()) {
return Actions.ActOnIdentifierExpr(CurScope, OperatorLoc, *II,
Tok.is(tok::l_paren), &SS);
+ } else if (TypeTy *Type = ParseConversionFunctionId()) {
+ return Actions.ActOnConversionFunctionExpr(CurScope, OperatorLoc,
+ Type, Tok.is(tok::l_paren),
+ &SS);
}
- // FIXME: Handle conversion-function-id.
- unsigned DiagID = PP.getDiagnostics().getCustomDiagID(Diagnostic::Error,
- "expected operator-function-id");
- return Diag(Tok, DiagID);
+
+ // We already complained about a bad conversion-function-id,
+ // above.
+ return true;
}
} // switch.
diff --git a/clang/lib/Sema/IdentifierResolver.cpp b/clang/lib/Sema/IdentifierResolver.cpp
index 82f95bf1082..cf0342fe1b3 100644
--- a/clang/lib/Sema/IdentifierResolver.cpp
+++ b/clang/lib/Sema/IdentifierResolver.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
// This file implements the IdentifierResolver class, which is used for lexical
-// scoped lookup, based on identifier.
+// scoped lookup, based on declaration names.
//
//===----------------------------------------------------------------------===//
@@ -23,7 +23,7 @@ using namespace clang;
// IdDeclInfoMap class
//===----------------------------------------------------------------------===//
-/// IdDeclInfoMap - Associates IdDeclInfos with Identifiers.
+/// IdDeclInfoMap - Associates IdDeclInfos with declaration names.
/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
/// individual IdDeclInfo to heap.
class IdentifierResolver::IdDeclInfoMap {
@@ -36,9 +36,9 @@ class IdentifierResolver::IdDeclInfoMap {
public:
IdDeclInfoMap() : CurIndex(VECTOR_SIZE) {}
- /// Returns the IdDeclInfo associated to the IdentifierInfo.
+ /// Returns the IdDeclInfo associated to the DeclarationName.
/// It creates a new IdDeclInfo if one was not created before for this id.
- IdDeclInfo &operator[](IdentifierInfo *II);
+ IdDeclInfo &operator[](DeclarationName Name);
};
@@ -173,19 +173,19 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
/// AddDecl - Link the decl to its shadowed decl chain.
void IdentifierResolver::AddDecl(NamedDecl *D) {
- IdentifierInfo *II = D->getIdentifier();
- void *Ptr = II->getFETokenInfo<void>();
+ DeclarationName Name = D->getDeclName();
+ void *Ptr = Name.getFETokenInfo<void>();
if (!Ptr) {
- II->setFETokenInfo(D);
+ Name.setFETokenInfo(D);
return;
}
IdDeclInfo *IDI;
if (isDeclPtr(Ptr)) {
- II->setFETokenInfo(NULL);
- IDI = &(*IdDeclInfos)[II];
+ Name.setFETokenInfo(NULL);
+ IDI = &(*IdDeclInfos)[Name];
NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
IDI->AddDecl(PrevD);
} else
@@ -198,18 +198,18 @@ void IdentifierResolver::AddDecl(NamedDecl *D) {
/// after the decl that the iterator points to, thus the 'Shadow' decl will be
/// encountered before the 'D' decl.
void IdentifierResolver::AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow) {
- assert(D->getIdentifier() == Shadow->getIdentifier() && "Different ids!");
+ assert(D->getDeclName() == Shadow->getDeclName() && "Different ids!");
assert(LookupContext(D) == LookupContext(Shadow) && "Different context!");
- IdentifierInfo *II = D->getIdentifier();
- void *Ptr = II->getFETokenInfo<void>();
+ DeclarationName Name = D->getDeclName();
+ void *Ptr = Name.getFETokenInfo<void>();
assert(Ptr && "No decl from Ptr ?");
IdDeclInfo *IDI;
if (isDeclPtr(Ptr)) {
- II->setFETokenInfo(NULL);
- IDI = &(*IdDeclInfos)[II];
+ Name.setFETokenInfo(NULL);
+ IDI = &(*IdDeclInfos)[Name];
NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
assert(PrevD == Shadow && "Invalid shadow decl ?");
IDI->AddDecl(D);
@@ -225,29 +225,29 @@ void IdentifierResolver::AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow) {
/// The decl must already be part of the decl chain.
void IdentifierResolver::RemoveDecl(NamedDecl *D) {
assert(D && "null param passed");
- IdentifierInfo *II = D->getIdentifier();
- void *Ptr = II->getFETokenInfo<void>();
+ DeclarationName Name = D->getDeclName();
+ void *Ptr = Name.getFETokenInfo<void>();
assert(Ptr && "Didn't find this decl on its identifier's chain!");
if (isDeclPtr(Ptr)) {
assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
- II->setFETokenInfo(NULL);
+ Name.setFETokenInfo(NULL);
return;
}
return toIdDeclInfo(Ptr)->RemoveDecl(D);
}
-/// begin - Returns an iterator for decls of identifier 'II', starting at
+/// begin - Returns an iterator for decls with name 'Name', starting at
/// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the
/// decls of parent declaration contexts too.
IdentifierResolver::iterator
-IdentifierResolver::begin(const IdentifierInfo *II, const DeclContext *Ctx,
+IdentifierResolver::begin(DeclarationName Name, const DeclContext *Ctx,
bool LookInParentCtx) {
assert(Ctx && "null param passed");
- void *Ptr = II->getFETokenInfo<void>();
+ void *Ptr = Name.getFETokenInfo<void>();
if (!Ptr) return end();
LookupContext LC(Ctx);
@@ -284,7 +284,7 @@ IdentifierResolver::begin(const IdentifierInfo *II, const DeclContext *Ctx,
void IdentifierResolver::iterator::PreIncIter() {
NamedDecl *D = **this;
LookupContext Ctx(D);
- void *InfoPtr = D->getIdentifier()->getFETokenInfo<void>();
+ void *InfoPtr = D->getDeclName().getFETokenInfo<void>();
assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
@@ -310,12 +310,11 @@ void IdentifierResolver::iterator::PreIncIter() {
// IdDeclInfoMap Implementation
//===----------------------------------------------------------------------===//
-/// Returns the IdDeclInfo associated to the IdentifierInfo.
+/// Returns the IdDeclInfo associated to the DeclarationName.
/// It creates a new IdDeclInfo if one was not created before for this id.
IdentifierResolver::IdDeclInfo &
-IdentifierResolver::IdDeclInfoMap::operator[](IdentifierInfo *II) {
- assert (II && "null IdentifierInfo passed");
- void *Ptr = II->getFETokenInfo<void>();
+IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) {
+ void *Ptr = Name.getFETokenInfo<void>();
if (Ptr) return *toIdDeclInfo(Ptr);
@@ -327,7 +326,7 @@ IdentifierResolver::IdDeclInfoMap::operator[](IdentifierInfo *II) {
CurIndex = 0;
}
IdDeclInfo *IDI = &IDIVecs.back()[CurIndex];
- II->setFETokenInfo(reinterpret_cast<void*>(
+ Name.setFETokenInfo(reinterpret_cast<void*>(
reinterpret_cast<uintptr_t>(IDI) | 0x1)
);
++CurIndex;
diff --git a/clang/lib/Sema/IdentifierResolver.h b/clang/lib/Sema/IdentifierResolver.h
index e76bec6ee25..5a0f7467766 100644
--- a/clang/lib/Sema/IdentifierResolver.h
+++ b/clang/lib/Sema/IdentifierResolver.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
//
// This file defines the IdentifierResolver class, which is used for lexical
-// scoped lookup, based on identifier.
+// scoped lookup, based on declaration names.
//
//===----------------------------------------------------------------------===//
@@ -18,13 +18,14 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Parse/Scope.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/DeclCXX.h"
namespace clang {
-/// IdentifierResolver - Keeps track of shadowed decls on enclosing scopes.
-/// It manages the shadowing chains of identifiers and implements efficent decl
-/// lookup based on an identifier.
+/// IdentifierResolver - Keeps track of shadowed decls on enclosing
+/// scopes. It manages the shadowing chains of declaration names and
+/// implements efficent decl lookup based on a declaration name.
class IdentifierResolver {
/// LookupContext - A wrapper for DeclContext. DeclContext is only part of
@@ -79,10 +80,10 @@ class IdentifierResolver {
}
};
- /// IdDeclInfo - Keeps track of information about decls associated to a
- /// particular identifier. IdDeclInfos are lazily constructed and assigned
- /// to an identifier the first time a decl with that identifier is shadowed
- /// in some scope.
+ /// IdDeclInfo - Keeps track of information about decls associated
+ /// to a particular declaration name. IdDeclInfos are lazily
+ /// constructed and assigned to a declaration name the first time a
+ /// decl with that declaration name is shadowed in some scope.
class IdDeclInfo {
public:
typedef llvm::SmallVector<NamedDecl*, 2> DeclsTy;
@@ -123,7 +124,7 @@ class IdentifierResolver {
public:
- /// iterator - Iterate over the decls of a specified identifier.
+ /// iterator - Iterate over the decls of a specified declaration name.
/// It will walk or not the parent declaration contexts depending on how
/// it was instantiated.
class iterator {
@@ -192,11 +193,11 @@ public:
void PreIncIter();
};
- /// begin - Returns an iterator for decls of identifier 'II', starting at
+ /// begin - Returns an iterator for decls with the name 'Name', starting at
/// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the
/// decls of parent declaration contexts too.
/// Default for 'LookInParentCtx is true.
- static iterator begin(const IdentifierInfo *II, const DeclContext *Ctx,
+ static iterator begin(DeclarationName Name, const DeclContext *Ctx,
bool LookInParentCtx = true);
/// end - Returns an iterator that has 'finished'.
@@ -230,12 +231,12 @@ private:
class IdDeclInfoMap;
IdDeclInfoMap *IdDeclInfos;
- /// Identifier's FETokenInfo contains a Decl pointer if lower bit == 0.
+ /// FETokenInfo contains a Decl pointer if lower bit == 0.
static inline bool isDeclPtr(void *Ptr) {
return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
}
- /// Identifier's FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
+ /// FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
static inline IdDeclInfo *toIdDeclInfo(void *Ptr) {
assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1
&& "Ptr not a IdDeclInfo* !");
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index efe481abaef..50a12f13855 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -282,7 +282,7 @@ public:
//===--------------------------------------------------------------------===//
// Symbol table / Decl tracking callbacks: SemaDecl.cpp.
//
- virtual TypeTy *isTypeName(const IdentifierInfo &II, Scope *S,
+ virtual TypeTy *isTypeName(IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS);
virtual DeclTy *ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup);
virtual DeclTy *ActOnParamDeclarator(Scope *S, Declarator &D);
@@ -462,7 +462,7 @@ public:
void CheckExtraCXXDefaultArguments(Declarator &D);
/// More parsing and symbol table subroutines...
- Decl *LookupDecl(const IdentifierInfo *II, unsigned NSI, Scope *S,
+ Decl *LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
const DeclContext *LookupCtx = 0,
bool enableLazyBuiltinCreation = true);
ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *Id);
@@ -614,6 +614,11 @@ public:
IdentifierInfo &II,
bool HasTrailingLParen,
const CXXScopeSpec *SS = 0);
+ virtual ExprResult ActOnConversionFunctionExpr(Scope *S,
+ SourceLocation OperatorLoc,
+ TypeTy *Ty,
+ bool HasTrailingLParen,
+ const CXXScopeSpec *SS);
virtual ExprResult ActOnPredefinedExpr(SourceLocation Loc,
tok::TokenKind Kind);
virtual ExprResult ActOnNumericConstant(const Token &);
@@ -820,7 +825,7 @@ public:
const CXXScopeSpec &SS,
SourceLocation IdLoc,
SourceLocation CCLoc,
- const IdentifierInfo &II);
+ IdentifierInfo &II);
/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
/// scope or nested-name-specifier) is parsed, part of a declarator-id.
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 14805279b03..f22ca0c712c 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -20,9 +20,9 @@ using namespace clang;
namespace {
Decl *LookupNestedName(DeclContext *LookupCtx, bool LookInParentCtx,
- const IdentifierInfo &II, bool &IdIsUndeclared) {
+ DeclarationName Name, bool &IdIsUndeclared) {
IdentifierResolver::iterator
- I = IdentifierResolver::begin(&II, LookupCtx, LookInParentCtx),
+ I = IdentifierResolver::begin(Name, LookupCtx, LookInParentCtx),
E = IdentifierResolver::end();
if (I == E) {
@@ -67,15 +67,16 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
const CXXScopeSpec &SS,
SourceLocation IdLoc,
SourceLocation CCLoc,
- const IdentifierInfo &II) {
+ IdentifierInfo &II) {
DeclContext *DC = static_cast<DeclContext*>(SS.getScopeRep());
Decl *SD;
bool IdIsUndeclared;
if (DC)
- SD = LookupNestedName(DC, false/*LookInParentCtx*/, II, IdIsUndeclared);
+ SD = LookupNestedName(DC, false/*LookInParentCtx*/, &II, IdIsUndeclared);
else
- SD = LookupNestedName(CurContext, true/*LookInParent*/, II, IdIsUndeclared);
+ SD = LookupNestedName(CurContext, true/*LookInParent*/, &II,
+ IdIsUndeclared);
if (SD) {
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 816d6fd05d6..49c153d8c86 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -29,7 +29,12 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCallRaw) {
llvm::OwningPtr<CallExpr> TheCall(TheCallRaw);
// Get the IdentifierInfo* for the called function.
IdentifierInfo *FnInfo = FDecl->getIdentifier();
-
+
+ // None of the checks below are needed for functions that don't have
+ // simple names (e.g., C++ conversion functions).
+ if (!FnInfo)
+ return TheCall.take();
+
switch (FnInfo->getBuiltinID()) {
case Builtin::BI__builtin___CFStringMakeConstantString:
assert(TheCall->getNumArgs() == 1 &&
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 48073694a32..ea2a3ad9a75 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -28,7 +28,7 @@
#include "llvm/ADT/StringExtras.h"
using namespace clang;
-Sema::TypeTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S,
+Sema::TypeTy *Sema::isTypeName(IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS) {
DeclContext *DC = 0;
if (SS) {
@@ -113,7 +113,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
// We are pushing the name of a function, which might be an
// overloaded name.
IdentifierResolver::iterator
- I = IdResolver.begin(FD->getIdentifier(),
+ I = IdResolver.begin(FD->getDeclName(),
FD->getDeclContext(), false/*LookInParentCtx*/);
if (I != IdResolver.end() &&
IdResolver.isDeclInScope(*I, FD->getDeclContext(), S) &&
@@ -126,7 +126,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
// FunctionDecl and put it into an OverloadedFunctionDecl.
Ovl = OverloadedFunctionDecl::Create(Context,
FD->getDeclContext(),
- FD->getIdentifier());
+ FD->getDeclName());
Ovl->addOverload(dyn_cast<FunctionDecl>(*I));
// Remove the name binding to the existing FunctionDecl...
@@ -187,17 +187,17 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) {
/// LookupDecl - Look up the inner-most declaration in the specified
/// namespace.
-Decl *Sema::LookupDecl(const IdentifierInfo *II, unsigned NSI, Scope *S,
+Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
const DeclContext *LookupCtx,
bool enableLazyBuiltinCreation) {
- if (II == 0) return 0;
+ if (!Name) return 0;
unsigned NS = NSI;
if (getLangOptions().CPlusPlus && (NS & Decl::IDNS_Ordinary))
NS |= Decl::IDNS_Tag;
IdentifierResolver::iterator
- I = LookupCtx ? IdResolver.begin(II, LookupCtx, false/*LookInParentCtx*/) :
- IdResolver.begin(II, CurContext, true/*LookInParentCtx*/);
+ I = LookupCtx ? IdResolver.begin(Name, LookupCtx, false/*LookInParentCtx*/)
+ : IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/);
// Scan up the scope chain looking for a decl that matches this identifier
// that is in the appropriate namespace. This search should not take long, as
// shadowing of names is uncommon, and deep shadowing is extremely uncommon.
@@ -209,13 +209,14 @@ Decl *Sema::LookupDecl(const IdentifierInfo *II, unsigned NSI, Scope *S,
// corresponds to a compiler builtin, create the decl object for the builtin
// now, injecting it into translation unit scope, and return it.
if (NS & Decl::IDNS_Ordinary) {
- if (enableLazyBuiltinCreation &&
+ IdentifierInfo *II = Name.getAsIdentifierInfo();
+ if (enableLazyBuiltinCreation && II &&
(LookupCtx == 0 || isa<TranslationUnitDecl>(LookupCtx))) {
// If this is a builtin on this (or all) targets, create the decl.
if (unsigned BuiltinID = II->getBuiltinID())
return LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, S);
}
- if (getLangOptions().ObjC1) {
+ if (getLangOptions().ObjC1 && II) {
// @interface and @compatibility_alias introduce typedef-like names.
// Unlike typedef's, they can only be introduced at file-scope (and are
// therefore not scoped decls). They can, however, be shadowed by
@@ -1034,8 +1035,11 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
return ActOnConstructorDeclarator(Constructor);
else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(NewFD))
return ActOnDestructorDeclarator(Destructor);
- else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
- return ActOnConversionDeclarator(Conversion);
+
+ // Extra checking for conversion functions, including recording
+ // the conversion function in its class.
+ if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
+ ActOnConversionDeclarator(Conversion);
// Extra checking for C++ overloaded operators (C++ [over.oper]).
if (NewFD->isOverloadedOperator() &&
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index e420ce59916..e49ef27af77 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -19,6 +19,56 @@
#include "clang/Basic/Diagnostic.h"
using namespace clang;
+/// ActOnConversionFunctionExpr - Parse a C++ conversion function
+/// name (e.g., operator void const *) as an expression. This is
+/// very similar to ActOnIdentifierExpr, except that instead of
+/// providing an identifier the parser provides the type of the
+/// conversion function.
+Sema::ExprResult Sema::ActOnConversionFunctionExpr(Scope *S,
+ SourceLocation OperatorLoc,
+ TypeTy *Ty,
+ bool HasTrailingLParen,
+ const CXXScopeSpec *SS) {
+ QualType ConvType = QualType::getFromOpaquePtr(Ty);
+ QualType ConvTypeCanon = Context.getCanonicalType(ConvType);
+ DeclarationName ConvName
+ = Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon);
+
+ // We only expect to find a CXXConversionDecl.
+ Decl *D;
+ if (SS && !SS->isEmpty()) {
+ DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep());
+ if (DC == 0)
+ return true;
+ D = LookupDecl(ConvName, Decl::IDNS_Ordinary, S, DC);
+ } else
+ D = LookupDecl(ConvName, Decl::IDNS_Ordinary, S);
+
+ if (D == 0) {
+ // If there is no conversion function that converts to this type,
+ // diagnose the problem.
+ if (SS && !SS->isEmpty())
+ return Diag(OperatorLoc, diag::err_typecheck_no_member,
+ ConvType.getAsString(), SS->getRange());
+ else
+ return Diag(OperatorLoc, diag::err_no_conv_function,
+ ConvType.getAsString());
+ }
+
+ assert(isa<CXXConversionDecl>(D) && "we had to find a conversion function");
+ CXXConversionDecl *Conversion = cast<CXXConversionDecl>(D);
+
+ // check if referencing a declaration with __attribute__((deprecated)).
+ if (Conversion->getAttr<DeprecatedAttr>())
+ Diag(OperatorLoc, diag::warn_deprecated, Conversion->getName());
+
+ // Only create DeclRefExpr's for valid Decl's.
+ if (Conversion->isInvalidDecl())
+ return true;
+
+ // Create a normal DeclRefExpr.
+ return new DeclRefExpr(Conversion, Conversion->getType(), OperatorLoc);
+}
/// ActOnCXXTypeidOfType - Parse typeid( type-id ).
Action::ExprResult
OpenPOWER on IntegriCloud