Improve the representation of CXXUuidofExpr

Keep a pointer to the UuidAttr that the CXXUuidofExpr corresponds to.
This makes translating from __uuidof to the underlying constant a lot
more straightforward.

llvm-svn: 264529
This commit is contained in:
David Majnemer 2016-03-27 04:46:07 +00:00
parent ff379b69b2
commit 1dbc7a7a5a
5 changed files with 73 additions and 107 deletions

View File

@ -778,22 +778,23 @@ public:
class CXXUuidofExpr : public Expr {
private:
llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand;
const UuidAttr *UA;
SourceRange Range;
public:
CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R)
: Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary,
false, Operand->getType()->isDependentType(),
Operand->getType()->isInstantiationDependentType(),
Operand->getType()->containsUnexpandedParameterPack()),
Operand(Operand), Range(R) { }
CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, const UuidAttr *UA,
SourceRange R)
: Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false,
Operand->getType()->isDependentType(),
Operand->getType()->isInstantiationDependentType(),
Operand->getType()->containsUnexpandedParameterPack()),
Operand(Operand), UA(UA), Range(R) {}
CXXUuidofExpr(QualType Ty, Expr *Operand, SourceRange R)
: Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary,
false, Operand->isTypeDependent(),
Operand->isInstantiationDependent(),
Operand->containsUnexpandedParameterPack()),
Operand(Operand), Range(R) { }
CXXUuidofExpr(QualType Ty, Expr *Operand, const UuidAttr *UA, SourceRange R)
: Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false,
Operand->isTypeDependent(), Operand->isInstantiationDependent(),
Operand->containsUnexpandedParameterPack()),
Operand(Operand), UA(UA), Range(R) {}
CXXUuidofExpr(EmptyShell Empty, bool isExpr)
: Expr(CXXUuidofExprClass, Empty) {
@ -830,7 +831,7 @@ public:
Operand = E;
}
StringRef getUuidAsStringRef(ASTContext &Context) const;
StringRef getUuidAsStringRef() const;
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
@ -841,11 +842,6 @@ public:
return T->getStmtClass() == CXXUuidofExprClass;
}
/// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to
/// a single GUID.
static const UuidAttr *GetUuidAttrOfType(QualType QT,
bool *HasMultipleGUIDsPtr = nullptr);
// Iterators
child_range children() {
if (isTypeOperand())

View File

@ -54,77 +54,8 @@ QualType CXXUuidofExpr::getTypeOperand(ASTContext &Context) const {
Operand.get<TypeSourceInfo *>()->getType().getNonReferenceType(), Quals);
}
// static
const UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT,
bool *RDHasMultipleGUIDsPtr) {
// Optionally remove one level of pointer, reference or array indirection.
const Type *Ty = QT.getTypePtr();
if (QT->isPointerType() || QT->isReferenceType())
Ty = QT->getPointeeType().getTypePtr();
else if (QT->isArrayType())
Ty = Ty->getBaseElementTypeUnsafe();
const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
if (!RD)
return nullptr;
if (const UuidAttr *Uuid = RD->getMostRecentDecl()->getAttr<UuidAttr>())
return Uuid;
// __uuidof can grab UUIDs from template arguments.
if (const ClassTemplateSpecializationDecl *CTSD =
dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
const TemplateArgumentList &TAL = CTSD->getTemplateArgs();
const UuidAttr *UuidForRD = nullptr;
for (const TemplateArgument &TA : TAL.asArray()) {
bool SeenMultipleGUIDs = false;
const UuidAttr *UuidForTA = nullptr;
if (TA.getKind() == TemplateArgument::Type)
UuidForTA = GetUuidAttrOfType(TA.getAsType(), &SeenMultipleGUIDs);
else if (TA.getKind() == TemplateArgument::Declaration)
UuidForTA =
GetUuidAttrOfType(TA.getAsDecl()->getType(), &SeenMultipleGUIDs);
// If the template argument has a UUID, there are three cases:
// - This is the first UUID seen for this RecordDecl.
// - This is a different UUID than previously seen for this RecordDecl.
// - This is the same UUID than previously seen for this RecordDecl.
if (UuidForTA) {
if (!UuidForRD)
UuidForRD = UuidForTA;
else if (UuidForRD != UuidForTA)
SeenMultipleGUIDs = true;
}
// Seeing multiple UUIDs means that we couldn't find a UUID
if (SeenMultipleGUIDs) {
if (RDHasMultipleGUIDsPtr)
*RDHasMultipleGUIDsPtr = true;
return nullptr;
}
}
return UuidForRD;
}
return nullptr;
}
StringRef CXXUuidofExpr::getUuidAsStringRef(ASTContext &Context) const {
StringRef Uuid;
if (isTypeOperand())
Uuid = CXXUuidofExpr::GetUuidAttrOfType(getTypeOperand(Context))->getGuid();
else {
// Special case: __uuidof(0) means an all-zero GUID.
Expr *Op = getExprOperand();
if (!Op->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
Uuid = CXXUuidofExpr::GetUuidAttrOfType(Op->getType())->getGuid();
else
Uuid = "00000000-0000-0000-0000-000000000000";
}
return Uuid;
StringRef CXXUuidofExpr::getUuidAsStringRef() const {
return UA ? UA->getGuid() : "00000000-0000-0000-0000-000000000000";
}
// CXXScalarValueInitExpr

View File

@ -1186,7 +1186,7 @@ void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
// This CXXUuidofExpr is mangled as-if it were actually a VarDecl from
// const __s_GUID _GUID_{lower case UUID with underscores}
StringRef Uuid = UE->getUuidAsStringRef(Context.getASTContext());
StringRef Uuid = UE->getUuidAsStringRef();
std::string Name = "_GUID_" + Uuid.lower();
std::replace(Name.begin(), Name.end(), '-', '_');

View File

@ -1454,7 +1454,7 @@ ConstantAddress CodeGenModule::GetAddrOfUuidDescriptor(
const CXXUuidofExpr* E) {
// Sema has verified that IIDSource has a __declspec(uuid()), and that its
// well-formed.
StringRef Uuid = E->getUuidAsStringRef(Context);
StringRef Uuid = E->getUuidAsStringRef();
std::string Name = "_GUID_" + Uuid.lower();
std::replace(Name.begin(), Name.end(), '-', '_');

View File

@ -508,23 +508,60 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc);
}
/// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to
/// a single GUID.
static void
getUuidAttrOfType(Sema &SemaRef, QualType QT,
llvm::SmallSetVector<const UuidAttr *, 1> &UuidAttrs) {
// Optionally remove one level of pointer, reference or array indirection.
const Type *Ty = QT.getTypePtr();
if (QT->isPointerType() || QT->isReferenceType())
Ty = QT->getPointeeType().getTypePtr();
else if (QT->isArrayType())
Ty = Ty->getBaseElementTypeUnsafe();
const auto *RD = Ty->getAsCXXRecordDecl();
if (!RD)
return;
if (const auto *Uuid = RD->getMostRecentDecl()->getAttr<UuidAttr>()) {
UuidAttrs.insert(Uuid);
return;
}
// __uuidof can grab UUIDs from template arguments.
if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
const TemplateArgumentList &TAL = CTSD->getTemplateArgs();
for (const TemplateArgument &TA : TAL.asArray()) {
const UuidAttr *UuidForTA = nullptr;
if (TA.getKind() == TemplateArgument::Type)
getUuidAttrOfType(SemaRef, TA.getAsType(), UuidAttrs);
else if (TA.getKind() == TemplateArgument::Declaration)
getUuidAttrOfType(SemaRef, TA.getAsDecl()->getType(), UuidAttrs);
if (UuidForTA)
UuidAttrs.insert(UuidForTA);
}
}
}
/// \brief Build a Microsoft __uuidof expression with a type operand.
ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
SourceLocation TypeidLoc,
TypeSourceInfo *Operand,
SourceLocation RParenLoc) {
const UuidAttr *UA = nullptr;
if (!Operand->getType()->isDependentType()) {
bool HasMultipleGUIDs = false;
if (!CXXUuidofExpr::GetUuidAttrOfType(Operand->getType(),
&HasMultipleGUIDs)) {
if (HasMultipleGUIDs)
return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids));
else
return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
}
llvm::SmallSetVector<const UuidAttr *, 1> UuidAttrs;
getUuidAttrOfType(*this, Operand->getType(), UuidAttrs);
if (UuidAttrs.empty())
return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
if (UuidAttrs.size() > 1)
return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids));
UA = UuidAttrs.back();
}
return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand,
return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand, UA,
SourceRange(TypeidLoc, RParenLoc));
}
@ -533,18 +570,20 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
SourceLocation TypeidLoc,
Expr *E,
SourceLocation RParenLoc) {
const UuidAttr *UA = nullptr;
if (!E->getType()->isDependentType()) {
bool HasMultipleGUIDs = false;
if (!CXXUuidofExpr::GetUuidAttrOfType(E->getType(), &HasMultipleGUIDs) &&
!E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
if (HasMultipleGUIDs)
return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids));
else
if (!E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
llvm::SmallSetVector<const UuidAttr *, 1> UuidAttrs;
getUuidAttrOfType(*this, E->getType(), UuidAttrs);
if (UuidAttrs.empty())
return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
if (UuidAttrs.size() > 1)
return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids));
UA = UuidAttrs.back();
}
}
return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), E,
return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), E, UA,
SourceRange(TypeidLoc, RParenLoc));
}