summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/PrettyPrinter.h5
-rw-r--r--clang/include/clang/AST/Type.h8
-rw-r--r--clang/lib/AST/TypePrinter.cpp31
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp6
-rw-r--r--clang/test/SemaCXX/static-assert-cxx17.cpp41
-rw-r--r--clang/test/SemaCXX/static-assert.cpp15
6 files changed, 92 insertions, 14 deletions
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index 0a4dc42898f..3c877f5ea19 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -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;
};
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 5b69570aab4..cff63d0926e 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -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) {
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 031b44f11e3..32c75afb438 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -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(raw_ostream &OS) {
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(const Type *T,
}
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 *T,Qualifiers Quals, raw_ostream &OS) {
}
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 Type *ty, Qualifiers qs,
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, Qualifiers qs,
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) {
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index c1763528dfe..e0f4d2e4950 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3122,8 +3122,10 @@ Sema::findFailedBooleanCondition(Expr *Cond) {
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 };
}
diff --git a/clang/test/SemaCXX/static-assert-cxx17.cpp b/clang/test/SemaCXX/static-assert-cxx17.cpp
index 67b3541bea1..7fff59e7f80 100644
--- a/clang/test/SemaCXX/static-assert-cxx17.cpp
+++ b/clang/test/SemaCXX/static-assert-cxx17.cpp
@@ -54,3 +54,44 @@ void foo5() {
}
template void foo5<int, float>();
// expected-note@-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@-1{{static_assert failed due to requirement 'X<int>()'}}
+ static_assert(X<typename T::T>{});
+ // expected-error@-1{{static_assert failed due to requirement 'X<int>{}'}}
+ static_assert(X<typename T::T>{1, 2});
+ // expected-error@-1{{static_assert failed due to requirement 'X<int>{1, 2}'}}
+ static_assert(X<typename T::T>({1, 2}));
+ // expected-error@-1{{static_assert failed due to requirement 'X<int>({1, 2})'}}
+ static_assert(typename T::T{0});
+ // expected-error@-1{{static_assert failed due to requirement 'int{0}'}}
+ static_assert(typename T::T(0));
+ // expected-error@-1{{static_assert failed due to requirement 'int(0)'}}
+ static_assert(sizeof(X<typename T::T>) == 0);
+ // expected-error@-1{{static_assert failed due to requirement 'sizeof(X<int>) == 0'}}
+ static_assert((const X<typename T::T> *)nullptr);
+ // expected-error@-1{{static_assert failed due to requirement '(const X<int> *)nullptr'}}
+ static_assert(static_cast<const X<typename T::T> *>(nullptr));
+ // expected-error@-1{{static_assert failed due to requirement 'static_cast<const X<int> *>(nullptr)'}}
+ static_assert((const X<typename T::T>[]){} == nullptr);
+ // expected-error@-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@-1{{static_assert failed due to requirement 'sizeof(X<void>) == 0'}}
+}
+template void foo6<ExampleTypes>();
+// expected-note@-1{{in instantiation of function template specialization 'foo6<ExampleTypes>' requested here}}
diff --git a/clang/test/SemaCXX/static-assert.cpp b/clang/test/SemaCXX/static-assert.cpp
index b43d56a922c..a21cc874b56 100644
--- a/clang/test/SemaCXX/static-assert.cpp
+++ b/clang/test/SemaCXX/static-assert.cpp
@@ -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 ExampleTypes::T>::value == false, "message");
// expected-error@-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@-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@-1{{static_assert failed due to requirement 'std::is_const<int>()' "message"}}
+static_assert(!(std::is_const<const ExampleTypes::T>()()), "message");
+// expected-error@-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@-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@-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@-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@-1{{static_assert failed due to requirement 'std::is_const<ExampleTypes>::value' "message"}}
struct BI_tag {};
struct RAI_tag : BI_tag {};
OpenPOWER on IntegriCloud