<p>Given
a <code>DeclarationName</code> <code>N</code>, <code>N.getNameKind()</code>
- will produce a valid that describes what kind of name <code>N</code>
+ will produce a value that describes what kind of name <code>N</code>
stores. There are 7 options (all of the names are inside
the <code>DeclarationName</code> class)</p>
<dl>
case OverloadedFunction:
case CXXField:
case CXXMethod:
+ case CXXConversion:
case CXXClassVar:
return IDNS_Ordinary;
case Record:
friend class DeclarationNameTable;
+ /// getFETokenInfoAsVoid - Retrieves the front end-specified pointer
+ /// for this name as a void pointer.
+ void *getFETokenInfoAsVoid() const;
+
public:
/// DeclarationName - Used to create an empty selector.
DeclarationName() : Ptr(0) { }
// Construct a declaration name from an Objective-C selector.
DeclarationName(Selector Sel);
+ // operator bool() - Evaluates true when this declaration name is
+ // non-empty.
+ operator bool() const {
+ return ((Ptr & PtrMask) != 0) ||
+ (reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask));
+ }
+
/// getNameKind - Determine what kind of name this is.
NameKind getNameKind() const;
/// declaration name.
Selector getObjCSelector() const;
+ /// getFETokenInfo/setFETokenInfo - The language front-end is
+ /// allowed to associate arbitrary metadata with some kinds of
+ /// declaration names, including normal identifiers and C++
+ /// constructors, destructors, and conversion functions.
+ template<typename T>
+ T *getFETokenInfo() const { return static_cast<T*>(getFETokenInfoAsVoid()); }
+
+ void setFETokenInfo(void *T);
+
/// operator== - Determine whether the specified names are identical..
friend bool operator==(DeclarationName LHS, DeclarationName RHS) {
return LHS.Ptr == RHS.Ptr;
DIAG(warn_conv_to_self_not_used, WARNING,
"conversion function converting '%0' to itself will never be used")
DIAG(warn_conv_to_base_not_used, WARNING,
- "conversion function converting '%0' to its base class '%1' will never be used")
+ "conversion function converting '%0' to its base class '%1' will never "
+ "be used")
DIAG(warn_conv_to_void_not_used, WARNING,
"conversion function converting '%0' to '%1' will never be used")
+DIAG(err_no_conv_function, ERROR,
+ "no conversion function to type '%0'")
DIAG(warn_not_compound_assign, WARNING,
/// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or
/// namespace) that the identifier must be a member of.
/// i.e. for "foo::bar", 'II' will be "bar" and 'SS' will be "foo::".
- virtual TypeTy *isTypeName(const IdentifierInfo &II, Scope *S,
+ virtual TypeTy *isTypeName(IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS = 0) = 0;
/// isCurrentClassName - Return true if the specified name is the
const CXXScopeSpec &SS,
SourceLocation IdLoc,
SourceLocation CCLoc,
- const IdentifierInfo &II) {
+ IdentifierInfo &II) {
return 0;
}
return 0;
}
+ /// 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.
+ virtual ExprResult ActOnConversionFunctionExpr(Scope *S,
+ SourceLocation OperatorLoc,
+ TypeTy *Type,
+ bool HasTrailingLParen,
+ const CXXScopeSpec *SS = 0) {
+ return 0;
+ }
+
virtual ExprResult ActOnPredefinedExpr(SourceLocation Loc,
tok::TokenKind Kind) {
return 0;
/// isTypeName - This looks at the IdentifierInfo::FETokenInfo field to
/// determine whether the name is a typedef or not in this scope.
- virtual TypeTy *isTypeName(const IdentifierInfo &II, Scope *S,
+ virtual TypeTy *isTypeName(IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS);
/// isCurrentClassName - Always returns false, because MinimalAction
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());
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>;
}
CXXSpecialName *SpecialName = new CXXSpecialName;
SpecialName->ExtraKindOrNumArgs = EKind;
SpecialName->Type = Ty;
+ SpecialName->FETokenInfo = 0;
SpecialNames->InsertNode(SpecialName, InsertPos);
return DeclarationName(SpecialName);
///
/// 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)
// unqualified-id:
// identifier
// operator-function-id
- // conversion-function-id [TODO]
+ // conversion-function-id
// '~' class-name [TODO]
// template-id [TODO]
//
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.
//===----------------------------------------------------------------------===//
//
// This file implements the IdentifierResolver class, which is used for lexical
-// scoped lookup, based on identifier.
+// scoped lookup, based on declaration names.
//
//===----------------------------------------------------------------------===//
// 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 {
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);
};
/// 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
/// 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);
/// 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);
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);
// 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);
CurIndex = 0;
}
IdDeclInfo *IDI = &IDIVecs.back()[CurIndex];
- II->setFETokenInfo(reinterpret_cast<void*>(
+ Name.setFETokenInfo(reinterpret_cast<void*>(
reinterpret_cast<uintptr_t>(IDI) | 0x1)
);
++CurIndex;
//===----------------------------------------------------------------------===//
//
// This file defines the IdentifierResolver class, which is used for lexical
-// scoped lookup, based on identifier.
+// scoped lookup, based on declaration names.
//
//===----------------------------------------------------------------------===//
#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
}
};
- /// 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;
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 {
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'.
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* !");
//===--------------------------------------------------------------------===//
// 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);
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);
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 &);
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.
\r
namespace {\r
Decl *LookupNestedName(DeclContext *LookupCtx, bool LookInParentCtx,\r
- const IdentifierInfo &II, bool &IdIsUndeclared) {\r
+ DeclarationName Name, bool &IdIsUndeclared) {\r
IdentifierResolver::iterator\r
- I = IdentifierResolver::begin(&II, LookupCtx, LookInParentCtx),\r
+ I = IdentifierResolver::begin(Name, LookupCtx, LookInParentCtx),\r
E = IdentifierResolver::end();\r
\r
if (I == E) {\r
const CXXScopeSpec &SS,\r
SourceLocation IdLoc,\r
SourceLocation CCLoc,\r
- const IdentifierInfo &II) {\r
+ IdentifierInfo &II) {\r
DeclContext *DC = static_cast<DeclContext*>(SS.getScopeRep());\r
Decl *SD;\r
bool IdIsUndeclared;\r
\r
if (DC)\r
- SD = LookupNestedName(DC, false/*LookInParentCtx*/, II, IdIsUndeclared);\r
+ SD = LookupNestedName(DC, false/*LookInParentCtx*/, &II, IdIsUndeclared);\r
else\r
- SD = LookupNestedName(CurContext, true/*LookInParent*/, II, IdIsUndeclared);\r
+ SD = LookupNestedName(CurContext, true/*LookInParent*/, &II, \r
+ IdIsUndeclared);\r
\r
if (SD) {\r
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {\r
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 &&
#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) {
// 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) &&
// 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...
/// 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.
// 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
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() &&
#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
public:
operator bool();
operator int() const;
+
+ bool f() {
+ return operator bool();
+ }
+
+ float g() {
+ return operator float(); // expected-error{{no conversion function to type 'float'}}
+ }
};
operator int(); // expected-error{{conversion function must be a non-static member function}}