r349729 - [Sema] Better static assert diagnostics for expressions involving temporaries/casts/....
Clement Courbet via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 20 01:05:15 PST 2018
Author: courbet
Date: Thu Dec 20 01:05:15 2018
New Revision: 349729
URL: http://llvm.org/viewvc/llvm-project?rev=349729&view=rev
Log:
[Sema] Better static assert diagnostics for expressions involving temporaries/casts/....
Summary:
Handles expressions such as:
- `std::is_const<T>()`
- `std::is_const<T>()()`;
- `std::is_same(decltype(U()), V>::value`;
Reviewers: aaron.ballman, Quuxplusone
Subscribers: cfe-commits, llvm-commits
Differential Revision: https://reviews.llvm.org/D55552
Modified:
cfe/trunk/include/clang/AST/PrettyPrinter.h
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/lib/AST/TypePrinter.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/SemaCXX/static-assert-cxx17.cpp
cfe/trunk/test/SemaCXX/static-assert.cpp
Modified: cfe/trunk/include/clang/AST/PrettyPrinter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/PrettyPrinter.h?rev=349729&r1=349728&r2=349729&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/PrettyPrinter.h (original)
+++ cfe/trunk/include/clang/AST/PrettyPrinter.h Thu Dec 20 01:05:15 2018
@@ -51,7 +51,7 @@ struct PrintingPolicy {
MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true),
MSVCFormatting(false), ConstantsAsWritten(false),
SuppressImplicitBase(false), FullyQualifiedName(false),
- RemapFilePaths(false) {}
+ RemapFilePaths(false), PrintCanonicalTypes(false) {}
/// Adjust this printing policy for cases where it's known that we're
/// printing C++ code (for instance, if AST dumping reaches a C++-only
@@ -228,6 +228,9 @@ struct PrintingPolicy {
/// Whether to apply -fdebug-prefix-map to any file paths.
unsigned RemapFilePaths : 1;
+ /// Whether to print types as written or canonically.
+ unsigned PrintCanonicalTypes : 1;
+
/// When RemapFilePaths is true, this function performs the action.
std::function<std::string(StringRef)> remapPath;
};
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=349729&r1=349728&r2=349729&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Thu Dec 20 01:05:15 2018
@@ -980,9 +980,7 @@ public:
void print(raw_ostream &OS, const PrintingPolicy &Policy,
const Twine &PlaceHolder = Twine(),
- unsigned Indentation = 0) const {
- print(split(), OS, Policy, PlaceHolder, Indentation);
- }
+ unsigned Indentation = 0) const;
static void print(SplitQualType split, raw_ostream &OS,
const PrintingPolicy &policy, const Twine &PlaceHolder,
@@ -996,9 +994,7 @@ public:
unsigned Indentation = 0);
void getAsStringInternal(std::string &Str,
- const PrintingPolicy &Policy) const {
- return getAsStringInternal(split(), Str, Policy);
- }
+ const PrintingPolicy &Policy) const;
static void getAsStringInternal(SplitQualType split, std::string &out,
const PrintingPolicy &policy) {
Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=349729&r1=349728&r2=349729&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Thu Dec 20 01:05:15 2018
@@ -117,9 +117,7 @@ namespace {
void spaceBeforePlaceHolder(raw_ostream &OS);
void printTypeSpec(NamedDecl *D, raw_ostream &OS);
- void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS);
void printBefore(QualType T, raw_ostream &OS);
- void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS);
void printAfter(QualType T, raw_ostream &OS);
void AppendScope(DeclContext *DC, raw_ostream &OS);
void printTag(TagDecl *T, raw_ostream &OS);
@@ -129,6 +127,10 @@ namespace {
void print##CLASS##Before(const CLASS##Type *T, raw_ostream &OS); \
void print##CLASS##After(const CLASS##Type *T, raw_ostream &OS);
#include "clang/AST/TypeNodes.def"
+
+ private:
+ void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS);
+ void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS);
};
} // namespace
@@ -160,8 +162,15 @@ void TypePrinter::spaceBeforePlaceHolder
OS << ' ';
}
+static SplitQualType splitAccordingToPolicy(QualType QT,
+ const PrintingPolicy &Policy) {
+ if (Policy.PrintCanonicalTypes)
+ QT = QT.getCanonicalType();
+ return QT.split();
+}
+
void TypePrinter::print(QualType t, raw_ostream &OS, StringRef PlaceHolder) {
- SplitQualType split = t.split();
+ SplitQualType split = splitAccordingToPolicy(t, Policy);
print(split.Ty, split.Quals, OS, PlaceHolder);
}
@@ -260,7 +269,7 @@ bool TypePrinter::canPrefixQualifiers(co
}
void TypePrinter::printBefore(QualType T, raw_ostream &OS) {
- SplitQualType Split = T.split();
+ SplitQualType Split = splitAccordingToPolicy(T, Policy);
// If we have cv1 T, where T is substituted for cv2 U, only print cv1 - cv2
// at this level.
@@ -320,7 +329,7 @@ void TypePrinter::printBefore(const Type
}
void TypePrinter::printAfter(QualType t, raw_ostream &OS) {
- SplitQualType split = t.split();
+ SplitQualType split = splitAccordingToPolicy(t, Policy);
printAfter(split.Ty, split.Quals, OS);
}
@@ -1815,6 +1824,12 @@ std::string QualType::getAsString(const
return buffer;
}
+void QualType::print(raw_ostream &OS, const PrintingPolicy &Policy,
+ const Twine &PlaceHolder, unsigned Indentation) const {
+ print(splitAccordingToPolicy(*this, Policy), OS, Policy, PlaceHolder,
+ Indentation);
+}
+
void QualType::print(const Type *ty, Qualifiers qs,
raw_ostream &OS, const PrintingPolicy &policy,
const Twine &PlaceHolder, unsigned Indentation) {
@@ -1824,6 +1839,12 @@ void QualType::print(const Type *ty, Qua
TypePrinter(policy, Indentation).print(ty, qs, OS, PH);
}
+void QualType::getAsStringInternal(std::string &Str,
+ const PrintingPolicy &Policy) const {
+ return getAsStringInternal(splitAccordingToPolicy(*this, Policy), Str,
+ Policy);
+}
+
void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
std::string &buffer,
const PrintingPolicy &policy) {
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=349729&r1=349728&r2=349729&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Dec 20 01:05:15 2018
@@ -3122,8 +3122,10 @@ Sema::findFailedBooleanCondition(Expr *C
std::string Description;
{
llvm::raw_string_ostream Out(Description);
- FailedBooleanConditionPrinterHelper Helper(getPrintingPolicy());
- FailedCond->printPretty(Out, &Helper, getPrintingPolicy());
+ PrintingPolicy Policy = getPrintingPolicy();
+ Policy.PrintCanonicalTypes = true;
+ FailedBooleanConditionPrinterHelper Helper(Policy);
+ FailedCond->printPretty(Out, &Helper, Policy, 0, "\n", nullptr);
}
return { FailedCond, Description };
}
Modified: cfe/trunk/test/SemaCXX/static-assert-cxx17.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/static-assert-cxx17.cpp?rev=349729&r1=349728&r2=349729&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/static-assert-cxx17.cpp (original)
+++ cfe/trunk/test/SemaCXX/static-assert-cxx17.cpp Thu Dec 20 01:05:15 2018
@@ -54,3 +54,44 @@ void foo5() {
}
template void foo5<int, float>();
// expected-note at -1{{in instantiation of function template specialization 'foo5<int, float>' requested here}}
+
+struct ExampleTypes {
+ explicit ExampleTypes(int);
+ using T = int;
+ using U = float;
+};
+
+template <class T>
+struct X {
+ int i = 0;
+ int j = 0;
+ constexpr operator bool() const { return false; }
+};
+
+template <class T>
+void foo6() {
+ static_assert(X<typename T::T>());
+ // expected-error at -1{{static_assert failed due to requirement 'X<int>()'}}
+ static_assert(X<typename T::T>{});
+ // expected-error at -1{{static_assert failed due to requirement 'X<int>{}'}}
+ static_assert(X<typename T::T>{1, 2});
+ // expected-error at -1{{static_assert failed due to requirement 'X<int>{1, 2}'}}
+ static_assert(X<typename T::T>({1, 2}));
+ // expected-error at -1{{static_assert failed due to requirement 'X<int>({1, 2})'}}
+ static_assert(typename T::T{0});
+ // expected-error at -1{{static_assert failed due to requirement 'int{0}'}}
+ static_assert(typename T::T(0));
+ // expected-error at -1{{static_assert failed due to requirement 'int(0)'}}
+ static_assert(sizeof(X<typename T::T>) == 0);
+ // expected-error at -1{{static_assert failed due to requirement 'sizeof(X<int>) == 0'}}
+ static_assert((const X<typename T::T> *)nullptr);
+ // expected-error at -1{{static_assert failed due to requirement '(const X<int> *)nullptr'}}
+ static_assert(static_cast<const X<typename T::T> *>(nullptr));
+ // expected-error at -1{{static_assert failed due to requirement 'static_cast<const X<int> *>(nullptr)'}}
+ static_assert((const X<typename T::T>[]){} == nullptr);
+ // expected-error at -1{{static_assert failed due to requirement '(X<int> const[0]){} == nullptr'}}
+ static_assert(sizeof(X<decltype(X<typename T::T>().X<typename T::T>::~X())>) == 0);
+ // expected-error at -1{{static_assert failed due to requirement 'sizeof(X<void>) == 0'}}
+}
+template void foo6<ExampleTypes>();
+// expected-note at -1{{in instantiation of function template specialization 'foo6<ExampleTypes>' requested here}}
Modified: cfe/trunk/test/SemaCXX/static-assert.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/static-assert.cpp?rev=349729&r1=349728&r2=349729&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/static-assert.cpp (original)
+++ cfe/trunk/test/SemaCXX/static-assert.cpp Thu Dec 20 01:05:15 2018
@@ -76,6 +76,8 @@ struct integral_constant {
static const Tp value = v;
typedef Tp value_type;
typedef integral_constant type;
+ constexpr operator value_type() const noexcept { return value; }
+ constexpr value_type operator()() const noexcept { return value; }
};
template <class Tp, Tp v>
@@ -103,6 +105,7 @@ struct is_same<T, T> {
} // namespace std
struct ExampleTypes {
+ explicit ExampleTypes(int);
using T = int;
using U = float;
};
@@ -119,6 +122,18 @@ static_assert(std::is_const<const Exampl
// expected-error at -1{{static_assert failed due to requirement 'std::is_const<const int>::value == false' "message"}}
static_assert(!(std::is_const<const ExampleTypes::T>::value == true), "message");
// expected-error at -1{{static_assert failed due to requirement '!(std::is_const<const int>::value == true)' "message"}}
+static_assert(std::is_const<ExampleTypes::T>(), "message");
+// expected-error at -1{{static_assert failed due to requirement 'std::is_const<int>()' "message"}}
+static_assert(!(std::is_const<const ExampleTypes::T>()()), "message");
+// expected-error at -1{{static_assert failed due to requirement '!(std::is_const<const int>()())' "message"}}
+static_assert(std::is_same<decltype(std::is_const<const ExampleTypes::T>()), int>::value, "message");
+// expected-error at -1{{static_assert failed due to requirement 'std::is_same<std::is_const<const int>, int>::value' "message"}}
+static_assert(std::is_const<decltype(ExampleTypes::T(3))>::value, "message");
+// expected-error at -1{{static_assert failed due to requirement 'std::is_const<int>::value' "message"}}
+static_assert(std::is_const<decltype(ExampleTypes::T())>::value, "message");
+// expected-error at -1{{static_assert failed due to requirement 'std::is_const<int>::value' "message"}}
+static_assert(std::is_const<decltype(ExampleTypes(3))>::value, "message");
+// expected-error at -1{{static_assert failed due to requirement 'std::is_const<ExampleTypes>::value' "message"}}
struct BI_tag {};
struct RAI_tag : BI_tag {};
More information about the cfe-commits
mailing list