More __uuidof validation:

1. Do not validate for uuid attribute if the type is template dependent.
2. Search every class declaration and definition for the uuid attribute.

llvm-svn: 122578
This commit is contained in:
Francois Pichet 2010-12-27 01:32:00 +00:00
parent 2ac8355ecd
commit b7577657cd
2 changed files with 39 additions and 18 deletions

View File

@ -372,16 +372,23 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc);
}
// Get the CXXRecordDecl associated with QT bypassing 1 level of pointer,
// reference or array type.
static CXXRecordDecl *GetCXXRecordOfUuidArg(QualType QT) {
/// Retrieve the UuidAttr associated with QT.
static UuidAttr *GetUuidAttrOfType(QualType QT) {
// Optionally remove one level of pointer, reference or array indirection.
Type *Ty = QT.getTypePtr();;
if (QT->isPointerType() || QT->isReferenceType())
Ty = QT->getPointeeType().getTypePtr();
else if (QT->isArrayType())
Ty = cast<ArrayType>(QT)->getElementType().getTypePtr();
return Ty->getAsCXXRecordDecl();
// Loop all class definition and declaration looking for an uuid attribute.
CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
while (RD) {
if (UuidAttr *Uuid = RD->getAttr<UuidAttr>())
return Uuid;
RD = RD->getPreviousDeclaration();
}
return 0;
}
/// \brief Build a Microsoft __uuidof expression with a type operand.
@ -389,10 +396,10 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
SourceLocation TypeidLoc,
TypeSourceInfo *Operand,
SourceLocation RParenLoc) {
// Make sure Operand has an associated GUID.
CXXRecordDecl* RD = GetCXXRecordOfUuidArg(Operand->getType());
if (!RD || !RD->getAttr<UuidAttr>())
if (!Operand->getType()->isDependentType()) {
if (!GetUuidAttrOfType(Operand->getType()))
return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
}
// FIXME: add __uuidof semantic analysis for type operand.
return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(),
@ -405,14 +412,12 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType,
SourceLocation TypeidLoc,
Expr *E,
SourceLocation RParenLoc) {
// Make sure E has an associated GUID.
// 0 is fine also.
CXXRecordDecl* RD = GetCXXRecordOfUuidArg(E->getType());
if ((!RD || !RD->getAttr<UuidAttr>()) &&
if (!E->getType()->isDependentType()) {
if (!GetUuidAttrOfType(E->getType()) &&
!E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid));
// FIXME: add __uuidof semantic analysis for expr operand.
}
// FIXME: add __uuidof semantic analysis for type operand.
return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(),
E,
SourceRange(TypeidLoc, RParenLoc)));

View File

@ -48,6 +48,11 @@ struct __declspec(uuid("000000A0-0000-0000-C000-000000000046"))
struct_with_uuid { };
struct struct_without_uuid { };
struct __declspec(uuid("000000A0-0000-0000-C000-000000000049"))
struct_with_uuid2;
struct
struct_with_uuid2 {} ;
int uuid_sema_test()
{
@ -55,6 +60,7 @@ int uuid_sema_test()
struct_without_uuid var_without_uuid[1];
__uuidof(struct_with_uuid);
__uuidof(struct_with_uuid2);
__uuidof(struct_without_uuid); // expected-error {{cannot call operator __uuidof on a type with no GUID}}
__uuidof(struct_with_uuid*);
__uuidof(struct_without_uuid*); // expected-error {{cannot call operator __uuidof on a type with no GUID}}
@ -69,3 +75,13 @@ int uuid_sema_test()
__uuidof(0);
__uuidof(1);// expected-error {{cannot call operator __uuidof on a type with no GUID}}
}
template <class T>
void template_uuid()
{
T expr;
__uuidof(T);
__uuidof(expr);
}