forked from OSchip/llvm-project
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 {
|
||||
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())
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(), '-', '_');
|
||||
|
||||
|
|
|
@ -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(), '-', '_');
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue