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:
parent
ff379b69b2
commit
1dbc7a7a5a
|
@ -778,22 +778,23 @@ public:
|
||||||
class CXXUuidofExpr : public Expr {
|
class CXXUuidofExpr : public Expr {
|
||||||
private:
|
private:
|
||||||
llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand;
|
llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand;
|
||||||
|
const UuidAttr *UA;
|
||||||
SourceRange Range;
|
SourceRange Range;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R)
|
CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, const UuidAttr *UA,
|
||||||
: Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary,
|
SourceRange R)
|
||||||
false, Operand->getType()->isDependentType(),
|
: Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false,
|
||||||
Operand->getType()->isInstantiationDependentType(),
|
Operand->getType()->isDependentType(),
|
||||||
Operand->getType()->containsUnexpandedParameterPack()),
|
Operand->getType()->isInstantiationDependentType(),
|
||||||
Operand(Operand), Range(R) { }
|
Operand->getType()->containsUnexpandedParameterPack()),
|
||||||
|
Operand(Operand), UA(UA), Range(R) {}
|
||||||
|
|
||||||
CXXUuidofExpr(QualType Ty, Expr *Operand, SourceRange R)
|
CXXUuidofExpr(QualType Ty, Expr *Operand, const UuidAttr *UA, SourceRange R)
|
||||||
: Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary,
|
: Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false,
|
||||||
false, Operand->isTypeDependent(),
|
Operand->isTypeDependent(), Operand->isInstantiationDependent(),
|
||||||
Operand->isInstantiationDependent(),
|
Operand->containsUnexpandedParameterPack()),
|
||||||
Operand->containsUnexpandedParameterPack()),
|
Operand(Operand), UA(UA), Range(R) {}
|
||||||
Operand(Operand), Range(R) { }
|
|
||||||
|
|
||||||
CXXUuidofExpr(EmptyShell Empty, bool isExpr)
|
CXXUuidofExpr(EmptyShell Empty, bool isExpr)
|
||||||
: Expr(CXXUuidofExprClass, Empty) {
|
: Expr(CXXUuidofExprClass, Empty) {
|
||||||
|
@ -830,7 +831,7 @@ public:
|
||||||
Operand = E;
|
Operand = E;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef getUuidAsStringRef(ASTContext &Context) const;
|
StringRef getUuidAsStringRef() const;
|
||||||
|
|
||||||
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
|
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
|
||||||
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
|
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
|
||||||
|
@ -841,11 +842,6 @@ public:
|
||||||
return T->getStmtClass() == CXXUuidofExprClass;
|
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
|
// Iterators
|
||||||
child_range children() {
|
child_range children() {
|
||||||
if (isTypeOperand())
|
if (isTypeOperand())
|
||||||
|
|
|
@ -54,77 +54,8 @@ QualType CXXUuidofExpr::getTypeOperand(ASTContext &Context) const {
|
||||||
Operand.get<TypeSourceInfo *>()->getType().getNonReferenceType(), Quals);
|
Operand.get<TypeSourceInfo *>()->getType().getNonReferenceType(), Quals);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
StringRef CXXUuidofExpr::getUuidAsStringRef() const {
|
||||||
const UuidAttr *CXXUuidofExpr::GetUuidAttrOfType(QualType QT,
|
return UA ? UA->getGuid() : "00000000-0000-0000-0000-000000000000";
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CXXScalarValueInitExpr
|
// CXXScalarValueInitExpr
|
||||||
|
|
|
@ -1186,7 +1186,7 @@ void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) {
|
||||||
|
|
||||||
// This CXXUuidofExpr is mangled as-if it were actually a VarDecl from
|
// This CXXUuidofExpr is mangled as-if it were actually a VarDecl from
|
||||||
// const __s_GUID _GUID_{lower case UUID with underscores}
|
// 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::string Name = "_GUID_" + Uuid.lower();
|
||||||
std::replace(Name.begin(), Name.end(), '-', '_');
|
std::replace(Name.begin(), Name.end(), '-', '_');
|
||||||
|
|
||||||
|
|
|
@ -1454,7 +1454,7 @@ ConstantAddress CodeGenModule::GetAddrOfUuidDescriptor(
|
||||||
const CXXUuidofExpr* E) {
|
const CXXUuidofExpr* E) {
|
||||||
// Sema has verified that IIDSource has a __declspec(uuid()), and that its
|
// Sema has verified that IIDSource has a __declspec(uuid()), and that its
|
||||||
// well-formed.
|
// well-formed.
|
||||||
StringRef Uuid = E->getUuidAsStringRef(Context);
|
StringRef Uuid = E->getUuidAsStringRef();
|
||||||
std::string Name = "_GUID_" + Uuid.lower();
|
std::string Name = "_GUID_" + Uuid.lower();
|
||||||
std::replace(Name.begin(), Name.end(), '-', '_');
|
std::replace(Name.begin(), Name.end(), '-', '_');
|
||||||
|
|
||||||
|
|
|
@ -508,23 +508,60 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
|
||||||
return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc);
|
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.
|
/// \brief Build a Microsoft __uuidof expression with a type operand.
|
||||||
ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
|
ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
|
||||||
SourceLocation TypeidLoc,
|
SourceLocation TypeidLoc,
|
||||||
TypeSourceInfo *Operand,
|
TypeSourceInfo *Operand,
|
||||||
SourceLocation RParenLoc) {
|
SourceLocation RParenLoc) {
|
||||||
|
const UuidAttr *UA = nullptr;
|
||||||
if (!Operand->getType()->isDependentType()) {
|
if (!Operand->getType()->isDependentType()) {
|
||||||
bool HasMultipleGUIDs = false;
|
llvm::SmallSetVector<const UuidAttr *, 1> UuidAttrs;
|
||||||
if (!CXXUuidofExpr::GetUuidAttrOfType(Operand->getType(),
|
getUuidAttrOfType(*this, Operand->getType(), UuidAttrs);
|
||||||
&HasMultipleGUIDs)) {
|
if (UuidAttrs.empty())
|
||||||
if (HasMultipleGUIDs)
|
return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
|
||||||
return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids));
|
if (UuidAttrs.size() > 1)
|
||||||
else
|
return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids));
|
||||||
return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
|
UA = UuidAttrs.back();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand,
|
return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand, UA,
|
||||||
SourceRange(TypeidLoc, RParenLoc));
|
SourceRange(TypeidLoc, RParenLoc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,18 +570,20 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
|
||||||
SourceLocation TypeidLoc,
|
SourceLocation TypeidLoc,
|
||||||
Expr *E,
|
Expr *E,
|
||||||
SourceLocation RParenLoc) {
|
SourceLocation RParenLoc) {
|
||||||
|
const UuidAttr *UA = nullptr;
|
||||||
if (!E->getType()->isDependentType()) {
|
if (!E->getType()->isDependentType()) {
|
||||||
bool HasMultipleGUIDs = false;
|
if (!E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
|
||||||
if (!CXXUuidofExpr::GetUuidAttrOfType(E->getType(), &HasMultipleGUIDs) &&
|
llvm::SmallSetVector<const UuidAttr *, 1> UuidAttrs;
|
||||||
!E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
|
getUuidAttrOfType(*this, E->getType(), UuidAttrs);
|
||||||
if (HasMultipleGUIDs)
|
if (UuidAttrs.empty())
|
||||||
return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids));
|
|
||||||
else
|
|
||||||
return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
|
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));
|
SourceRange(TypeidLoc, RParenLoc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue