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

View File

@ -48,6 +48,11 @@ struct __declspec(uuid("000000A0-0000-0000-C000-000000000046"))
struct_with_uuid { }; struct_with_uuid { };
struct struct_without_uuid { }; struct struct_without_uuid { };
struct __declspec(uuid("000000A0-0000-0000-C000-000000000049"))
struct_with_uuid2;
struct
struct_with_uuid2 {} ;
int uuid_sema_test() int uuid_sema_test()
{ {
@ -55,6 +60,7 @@ int uuid_sema_test()
struct_without_uuid var_without_uuid[1]; struct_without_uuid var_without_uuid[1];
__uuidof(struct_with_uuid); __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_without_uuid); // expected-error {{cannot call operator __uuidof on a type with no GUID}}
__uuidof(struct_with_uuid*); __uuidof(struct_with_uuid*);
__uuidof(struct_without_uuid*); // expected-error {{cannot call operator __uuidof on a type with no GUID}} __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(0);
__uuidof(1);// expected-error {{cannot call operator __uuidof on a type with no GUID}} __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);
}