summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2015-05-14 19:10:42 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2015-05-14 19:10:42 +0000
commita462b4c9acd157fe2e29e739faa899024089c4bb (patch)
tree42cac85719609d08a123953ce9dffb275dd30e13 /clang/lib/Sema
parent2d5814c2d4123bbf6e647d5550f1a9add141df2f (diff)
downloadbcm5719-llvm-a462b4c9acd157fe2e29e739faa899024089c4bb.tar.gz
bcm5719-llvm-a462b4c9acd157fe2e29e739faa899024089c4bb.zip
DR295: cv-qualifiers on function types are ignored in C++.
llvm-svn: 237383
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaType.cpp85
1 files changed, 48 insertions, 37 deletions
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 5a6cc2eabe3..8729f481d6d 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -688,6 +688,33 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
state.setCurrentChunkIndex(declarator.getNumTypeObjects());
}
+void diagnoseAndRemoveTypeQualifiers(Sema &S, const DeclSpec &DS,
+ unsigned &TypeQuals, QualType TypeSoFar,
+ unsigned RemoveTQs, unsigned DiagID) {
+ // If this occurs outside a template instantiation, warn the user about
+ // it; they probably didn't mean to specify a redundant qualifier.
+ typedef std::pair<DeclSpec::TQ, SourceLocation> QualLoc;
+ QualLoc Quals[] = {
+ QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()),
+ QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()),
+ QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc())
+ };
+
+ for (unsigned I = 0, N = llvm::array_lengthof(Quals); I != N; ++I) {
+ if (!(RemoveTQs & Quals[I].first))
+ continue;
+
+ if (S.ActiveTemplateInstantiations.empty()) {
+ if (TypeQuals & Quals[I].first)
+ S.Diag(Quals[I].second, DiagID)
+ << DeclSpec::getSpecifierName(Quals[I].first) << TypeSoFar
+ << FixItHint::CreateRemoval(Quals[I].second);
+ }
+
+ TypeQuals &= ~Quals[I].first;
+ }
+}
+
/// \brief Convert the specified declspec to the appropriate type
/// object.
/// \param state Specifies the declarator containing the declaration specifier
@@ -1117,24 +1144,22 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
-
- // 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."
- if (Result->isFunctionType() && TypeQuals) {
- if (TypeQuals & DeclSpec::TQ_const)
- S.Diag(DS.getConstSpecLoc(), diag::warn_typecheck_function_qualifiers)
- << Result << DS.getSourceRange();
- else if (TypeQuals & DeclSpec::TQ_volatile)
- S.Diag(DS.getVolatileSpecLoc(),
- diag::warn_typecheck_function_qualifiers)
- << Result << DS.getSourceRange();
- else {
- assert((TypeQuals & (DeclSpec::TQ_restrict | DeclSpec::TQ_atomic)) &&
- "Has CVRA quals but not C, V, R, or A?");
- // No diagnostic; we'll diagnose 'restrict' or '_Atomic' applied to a
- // function type later, in BuildQualifiedType.
- }
+ // Warn about CV qualifiers on function types.
+ // C99 6.7.3p8:
+ // If the specification of a function type includes any type qualifiers,
+ // the behavior is undefined.
+ // C++11 [dcl.fct]p7:
+ // The effect of a cv-qualifier-seq in a function declarator is not the
+ // same as adding cv-qualification on top of the function type. In the
+ // latter case, the cv-qualifiers are ignored.
+ if (TypeQuals && Result->isFunctionType()) {
+ diagnoseAndRemoveTypeQualifiers(
+ S, DS, TypeQuals, Result, DeclSpec::TQ_const | DeclSpec::TQ_volatile,
+ S.getLangOpts().CPlusPlus
+ ? diag::warn_typecheck_function_qualifiers_ignored
+ : diag::warn_typecheck_function_qualifiers_unspecified);
+ // No diagnostic for 'restrict' or '_Atomic' applied to a
+ // function type; we'll diagnose those later, in BuildQualifiedType.
}
// C++11 [dcl.ref]p1:
@@ -1145,25 +1170,11 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// There don't appear to be any other contexts in which a cv-qualified
// reference type could be formed, so the 'ill-formed' clause here appears
// to never happen.
- if (DS.getTypeSpecType() == DeclSpec::TST_typename &&
- TypeQuals && Result->isReferenceType()) {
- // If this occurs outside a template instantiation, warn the user about
- // it; they probably didn't mean to specify a redundant qualifier.
- typedef std::pair<DeclSpec::TQ, SourceLocation> QualLoc;
- QualLoc Quals[] = {
- QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()),
- QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()),
- QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc())
- };
- for (unsigned I = 0, N = llvm::array_lengthof(Quals); I != N; ++I) {
- if (S.ActiveTemplateInstantiations.empty()) {
- if (TypeQuals & Quals[I].first)
- S.Diag(Quals[I].second, diag::warn_typecheck_reference_qualifiers)
- << DeclSpec::getSpecifierName(Quals[I].first) << Result
- << FixItHint::CreateRemoval(Quals[I].second);
- }
- TypeQuals &= ~Quals[I].first;
- }
+ if (TypeQuals && Result->isReferenceType()) {
+ diagnoseAndRemoveTypeQualifiers(
+ S, DS, TypeQuals, Result,
+ DeclSpec::TQ_const | DeclSpec::TQ_volatile | DeclSpec::TQ_atomic,
+ diag::warn_typecheck_reference_qualifiers);
}
// C90 6.5.3 constraints: "The same type qualifier shall not appear more
OpenPOWER on IntegriCloud