diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/DeclarationName.cpp | 39 | ||||
-rw-r--r-- | clang/lib/Parse/MinimalAction.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Sema/IdentifierResolver.cpp | 51 | ||||
-rw-r--r-- | clang/lib/Sema/IdentifierResolver.h | 27 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 11 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCXXScopeSpec.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 26 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 50 |
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 |