r178200 - Fold together the two implementations of 6.7.3p2 in SemaType. Fix two bugs, each of which was only present in one version:
Richard Smith
richard-llvm at metafoo.co.uk
Wed Mar 27 17:03:10 PDT 2013
Author: rsmith
Date: Wed Mar 27 19:03:10 2013
New Revision: 178200
URL: http://llvm.org/viewvc/llvm-project?rev=178200&view=rev
Log:
Fold together the two implementations of 6.7.3p2 in SemaType. Fix two bugs, each of which was only present in one version:
* Give the right diagnostic for 'restrict' applied to a non-pointer, non-reference type.
* Don't reject 'restrict' applied indirectly to an Objective-C object pointer type (eg, through template instantiation).
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/SemaObjCXX/parameters.mm
cfe/trunk/test/SemaTemplate/fun-template-def.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=178200&r1=178199&r2=178200&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Mar 27 19:03:10 2013
@@ -934,9 +934,11 @@ public:
// Type Analysis / Processing: SemaType.cpp.
//
- QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs);
- QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVR) {
- return BuildQualifiedType(T, Loc, Qualifiers::fromCVRMask(CVR));
+ QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs,
+ const DeclSpec *DS = 0);
+ QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVR,
+ const DeclSpec *DS = 0) {
+ return BuildQualifiedType(T, Loc, Qualifiers::fromCVRMask(CVR), DS);
}
QualType BuildPointerType(QualType T,
SourceLocation Loc, DeclarationName Entity);
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=178200&r1=178199&r2=178200&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Mar 27 19:03:10 2013
@@ -1085,35 +1085,6 @@ static QualType ConvertDeclSpecToType(Ty
// Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
- // Enforce C99 6.7.3p2: "Types other than pointer types derived from object
- // or incomplete types shall not be restrict-qualified." C++ also allows
- // restrict-qualified references.
- if (TypeQuals & DeclSpec::TQ_restrict) {
- if (Result->isAnyPointerType() || Result->isReferenceType()) {
- QualType EltTy;
- if (Result->isObjCObjectPointerType())
- EltTy = Result;
- else
- EltTy = Result->isPointerType() ?
- Result->getAs<PointerType>()->getPointeeType() :
- Result->getAs<ReferenceType>()->getPointeeType();
-
- // If we have a pointer or reference, the pointee must have an object
- // incomplete type.
- if (!EltTy->isIncompleteOrObjectType()) {
- S.Diag(DS.getRestrictSpecLoc(),
- diag::err_typecheck_invalid_restrict_invalid_pointee)
- << EltTy << DS.getSourceRange();
- TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
- }
- } else if (!Result->isDependentType()) {
- S.Diag(DS.getRestrictSpecLoc(),
- diag::err_typecheck_invalid_restrict_not_pointer)
- << Result << DS.getSourceRange();
- TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier.
- }
- }
-
// Warn about CV qualifiers on functions: C99 6.7.3p8: "If the specification
// of a function type includes any type qualifiers, the behavior is
// undefined."
@@ -1127,10 +1098,12 @@ static QualType ConvertDeclSpecToType(Ty
else {
assert((TypeQuals & DeclSpec::TQ_restrict) &&
"Has CVR quals but not C, V, or R?");
- Loc = DS.getRestrictSpecLoc();
+ // No diagnostic; we'll diagnose 'restrict' applied to a function type
+ // later, in BuildQualifiedType.
}
- S.Diag(Loc, diag::warn_typecheck_function_qualifiers)
- << Result << DS.getSourceRange();
+ if (!Loc.isInvalid())
+ S.Diag(Loc, diag::warn_typecheck_function_qualifiers)
+ << Result << DS.getSourceRange();
}
// C++ [dcl.ref]p1:
@@ -1164,8 +1137,7 @@ static QualType ConvertDeclSpecToType(Ty
// in this case.
}
- Qualifiers Quals = Qualifiers::fromCVRMask(TypeQuals);
- Result = Context.getQualifiedType(Result, Quals);
+ return S.BuildQualifiedType(Result, DeclLoc, TypeQuals, &DS);
}
return Result;
@@ -1179,37 +1151,36 @@ static std::string getPrintableNameForEn
}
QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
- Qualifiers Qs) {
+ Qualifiers Qs, const DeclSpec *DS) {
// Enforce C99 6.7.3p2: "Types other than pointer types derived from
// object or incomplete types shall not be restrict-qualified."
if (Qs.hasRestrict()) {
unsigned DiagID = 0;
QualType ProblemTy;
- const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
- if (const ReferenceType *RTy = dyn_cast<ReferenceType>(Ty)) {
- if (!RTy->getPointeeType()->isIncompleteOrObjectType()) {
- DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
- ProblemTy = T->getAs<ReferenceType>()->getPointeeType();
- }
- } else if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
- if (!PTy->getPointeeType()->isIncompleteOrObjectType()) {
- DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
- ProblemTy = T->getAs<PointerType>()->getPointeeType();
- }
- } else if (const MemberPointerType *PTy = dyn_cast<MemberPointerType>(Ty)) {
- if (!PTy->getPointeeType()->isIncompleteOrObjectType()) {
+ if (T->isAnyPointerType() || T->isReferenceType() ||
+ T->isMemberPointerType()) {
+ QualType EltTy;
+ if (T->isObjCObjectPointerType())
+ EltTy = T;
+ else if (const MemberPointerType *PTy = T->getAs<MemberPointerType>())
+ EltTy = PTy->getPointeeType();
+ else
+ EltTy = T->getPointeeType();
+
+ // If we have a pointer or reference, the pointee must have an object
+ // incomplete type.
+ if (!EltTy->isIncompleteOrObjectType()) {
DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
- ProblemTy = T->getAs<PointerType>()->getPointeeType();
+ ProblemTy = EltTy;
}
- } else if (!Ty->isDependentType()) {
- // FIXME: this deserves a proper diagnostic
- DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
+ } else if (!T->isDependentType()) {
+ DiagID = diag::err_typecheck_invalid_restrict_not_pointer;
ProblemTy = T;
}
if (DiagID) {
- Diag(Loc, DiagID) << ProblemTy;
+ Diag(DS ? DS->getRestrictSpecLoc() : Loc, DiagID) << ProblemTy;
Qs.removeRestrict();
}
}
Modified: cfe/trunk/test/SemaObjCXX/parameters.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/parameters.mm?rev=178200&r1=178199&r2=178200&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/parameters.mm (original)
+++ cfe/trunk/test/SemaObjCXX/parameters.mm Wed Mar 27 19:03:10 2013
@@ -15,3 +15,6 @@ struct test2 { virtual void foo() = 0; }
@interface Test2
- (void) foo: (test2) foo; // expected-error {{parameter type 'test2' is an abstract class}}
@end
+
+template<typename T> void r1(__restrict T);
+void r2(__restrict id x) { r1(x); }
Modified: cfe/trunk/test/SemaTemplate/fun-template-def.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/fun-template-def.cpp?rev=178200&r1=178199&r2=178200&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/fun-template-def.cpp (original)
+++ cfe/trunk/test/SemaTemplate/fun-template-def.cpp Wed Mar 27 19:03:10 2013
@@ -48,7 +48,7 @@ T f1(T t1, U u1, int i1)
}
template<typename T>
-void f2(__restrict T x) {} // expected-note {{substitution failure [with T = int]: pointer to function type 'int' may not be 'restrict' qualified}}
+void f2(__restrict T x) {} // expected-note {{substitution failure [with T = int]: restrict requires a pointer or reference ('int' is invalid}}
void f3() {
f2<int*>(0);
More information about the cfe-commits
mailing list