diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-03-28 00:03:10 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-03-28 00:03:10 +0000 |
commit | 93d6b07cd79d74e343d81c0e8fb5365376a33097 (patch) | |
tree | 83228486bce06c1ebd55784eb9bdef9970df55b0 | |
parent | ab2d09b6287a5dc6fa94d78739444f46f9a78bfb (diff) |
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).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178200 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Sema/Sema.h | 8 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 77 | ||||
-rw-r--r-- | test/SemaObjCXX/parameters.mm | 3 | ||||
-rw-r--r-- | test/SemaTemplate/fun-template-def.cpp | 2 |
4 files changed, 33 insertions, 57 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index d345e50d85..4259bb88ed 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 95df969eba..57f2aae80e 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1085,35 +1085,6 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // 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(TypeProcessingState &state) { 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(TypeProcessingState &state) { // 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 getPrintableNameForEntity(DeclarationName Entity) { } 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(); } } diff --git a/test/SemaObjCXX/parameters.mm b/test/SemaObjCXX/parameters.mm index 1a7869dc7a..363675a0dd 100644 --- a/test/SemaObjCXX/parameters.mm +++ b/test/SemaObjCXX/parameters.mm @@ -15,3 +15,6 @@ struct test2 { virtual void foo() = 0; }; // expected-note {{unimplemented}} @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); } diff --git a/test/SemaTemplate/fun-template-def.cpp b/test/SemaTemplate/fun-template-def.cpp index f57a045649..2d515b4b15 100644 --- a/test/SemaTemplate/fun-template-def.cpp +++ b/test/SemaTemplate/fun-template-def.cpp @@ -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); |