
C++ constructors, destructors, and conversion functions now have a FETokenInfo field that IdentifierResolver can access, so that these special names are handled just like ordinary identifiers. A few other Sema routines now use DeclarationNames instead of IdentifierInfo*'s. To validate this design, this code also implements parsing and semantic analysis for id-expressions that name conversion functions, e.g., return operator bool(); The new parser action ActOnConversionFunctionExpr takes the result of parsing "operator type-id" and turning it into an expression, using the IdentifierResolver with the DeclarationName of the conversion function. ActOnDeclarator pushes those conversion function names into scope so that the IdentifierResolver can find them, of course. llvm-svn: 59462
206 lines
5.8 KiB
C++
206 lines
5.8 KiB
C++
//===-- DeclarationName.cpp - Declaration names implementation --*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the DeclarationName and DeclarationNameTable
|
|
// classes.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#include "clang/AST/DeclarationName.h"
|
|
#include "clang/Basic/IdentifierTable.h"
|
|
#include "llvm/ADT/FoldingSet.h"
|
|
#include "llvm/Bitcode/Serialize.h"
|
|
#include "llvm/Bitcode/Deserialize.h"
|
|
using namespace clang;
|
|
|
|
namespace clang {
|
|
/// CXXSpecialName - Records the type associated with one of the
|
|
/// "special" kinds of declaration names in C++, e.g., constructors,
|
|
/// destructors, and conversion functions.
|
|
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());
|
|
}
|
|
};
|
|
|
|
bool operator<(DeclarationName LHS, DeclarationName RHS) {
|
|
if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo())
|
|
if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo())
|
|
return strcmp(LhsId->getName(), RhsId->getName()) < 0;
|
|
|
|
return LHS.getAsOpaqueInteger() < RHS.getAsOpaqueInteger();
|
|
}
|
|
|
|
} // end namespace clang
|
|
|
|
DeclarationName::DeclarationName(Selector Sel) {
|
|
switch (Sel.getNumArgs()) {
|
|
case 0:
|
|
Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
|
|
Ptr |= StoredObjCZeroArgSelector;
|
|
break;
|
|
|
|
case 1:
|
|
Ptr = reinterpret_cast<uintptr_t>(Sel.getAsIdentifierInfo());
|
|
Ptr |= StoredObjCOneArgSelector;
|
|
break;
|
|
|
|
default:
|
|
Ptr = Sel.InfoPtr & ~Selector::ArgFlags;
|
|
Ptr |= StoredObjCMultiArgSelectorOrCXXName;
|
|
break;
|
|
}
|
|
}
|
|
|
|
DeclarationName::NameKind DeclarationName::getNameKind() const {
|
|
switch (getStoredNameKind()) {
|
|
case StoredIdentifier: return Identifier;
|
|
case StoredObjCZeroArgSelector: return ObjCZeroArgSelector;
|
|
case StoredObjCOneArgSelector: return ObjCOneArgSelector;
|
|
|
|
case StoredObjCMultiArgSelectorOrCXXName:
|
|
switch (getExtra()->ExtraKindOrNumArgs) {
|
|
case DeclarationNameExtra::CXXConstructor:
|
|
return CXXConstructorName;
|
|
|
|
case DeclarationNameExtra::CXXDestructor:
|
|
return CXXDestructorName;
|
|
|
|
case DeclarationNameExtra::CXXConversionFunction:
|
|
return CXXConversionFunctionName;
|
|
|
|
default:
|
|
return ObjCMultiArgSelector;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Can't actually get here.
|
|
return Identifier;
|
|
}
|
|
|
|
QualType DeclarationName::getCXXNameType() const {
|
|
if (CXXSpecialName *CXXName = getAsCXXSpecialName())
|
|
return CXXName->Type;
|
|
else
|
|
return QualType();
|
|
}
|
|
|
|
Selector DeclarationName::getObjCSelector() const {
|
|
switch (getNameKind()) {
|
|
case ObjCZeroArgSelector:
|
|
return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 0);
|
|
|
|
case ObjCOneArgSelector:
|
|
return Selector(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask), 1);
|
|
|
|
case ObjCMultiArgSelector:
|
|
return Selector(reinterpret_cast<MultiKeywordSelector *>(Ptr & ~PtrMask));
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
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>;
|
|
}
|
|
|
|
DeclarationNameTable::~DeclarationNameTable() {
|
|
delete static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
|
|
}
|
|
|
|
DeclarationName
|
|
DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind,
|
|
QualType Ty) {
|
|
assert(Kind >= DeclarationName::CXXConstructorName &&
|
|
Kind <= DeclarationName::CXXConversionFunctionName &&
|
|
"Kind must be a C++ special name kind");
|
|
|
|
llvm::FoldingSet<CXXSpecialName> *SpecialNames
|
|
= static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl);
|
|
|
|
DeclarationNameExtra::ExtraKind EKind;
|
|
switch (Kind) {
|
|
case DeclarationName::CXXConstructorName:
|
|
EKind = DeclarationNameExtra::CXXConstructor;
|
|
break;
|
|
case DeclarationName::CXXDestructorName:
|
|
EKind = DeclarationNameExtra::CXXDestructor;
|
|
break;
|
|
case DeclarationName::CXXConversionFunctionName:
|
|
EKind = DeclarationNameExtra::CXXConversionFunction;
|
|
break;
|
|
default:
|
|
return DeclarationName();
|
|
}
|
|
|
|
// Unique selector, to guarantee there is one per name.
|
|
llvm::FoldingSetNodeID ID;
|
|
ID.AddInteger(EKind);
|
|
ID.AddPointer(Ty.getAsOpaquePtr());
|
|
|
|
void *InsertPos = 0;
|
|
if (CXXSpecialName *Name = SpecialNames->FindNodeOrInsertPos(ID, InsertPos))
|
|
return DeclarationName(Name);
|
|
|
|
CXXSpecialName *SpecialName = new CXXSpecialName;
|
|
SpecialName->ExtraKindOrNumArgs = EKind;
|
|
SpecialName->Type = Ty;
|
|
SpecialName->FETokenInfo = 0;
|
|
|
|
SpecialNames->InsertNode(SpecialName, InsertPos);
|
|
return DeclarationName(SpecialName);
|
|
}
|
|
|