summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/ASTContext.h10
-rw-r--r--clang/include/clang/AST/PrettyPrinter.h42
-rw-r--r--clang/lib/AST/DeclarationName.cpp27
-rw-r--r--clang/lib/AST/StmtPrinter.cpp6
-rw-r--r--clang/lib/AST/TypePrinter.cpp22
-rw-r--r--clang/lib/Parse/ParseDecl.cpp2
-rw-r--r--clang/lib/Sema/Sema.cpp9
-rw-r--r--clang/lib/Sema/SemaCodeComplete.cpp1
-rw-r--r--clang/test/Analysis/initializers-cfg-output.cpp2
-rw-r--r--clang/test/Analysis/temp-obj-dtors-cfg-output.cpp2
-rw-r--r--clang/test/SemaCXX/member-pointer.cpp9
11 files changed, 83 insertions, 49 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index b29593b73da..47f89c63613 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -243,6 +243,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType ObjCClassRedefinitionType;
QualType ObjCSelRedefinitionType;
+ /// The identifier 'bool'.
+ mutable IdentifierInfo *BoolName = nullptr;
+
/// The identifier 'NSObject'.
IdentifierInfo *NSObjectName = nullptr;
@@ -1457,6 +1460,13 @@ public:
return NSCopyingName;
}
+ /// Retrieve the identifier 'bool'.
+ IdentifierInfo *getBoolName() const {
+ if (!BoolName)
+ BoolName = &Idents.get("bool");
+ return BoolName;
+ }
+
IdentifierInfo *getMakeIntegerSeqName() const {
if (!MakeIntegerSeqName)
MakeIntegerSeqName = &Idents.get("__make_integer_seq");
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index df3e165c514..274df220e16 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -32,22 +32,35 @@ public:
/// \brief Describes how types, statements, expressions, and
/// declarations should be printed.
+///
+/// This type is intended to be small and suitable for passing by value.
+/// It is very frequently copied.
struct PrintingPolicy {
- /// \brief Create a default printing policy for C.
+ /// \brief Create a default printing policy for the specified language.
PrintingPolicy(const LangOptions &LO)
- : LangOpts(LO), Indentation(2), SuppressSpecifiers(false),
- SuppressTagKeyword(false),
+ : Indentation(2), SuppressSpecifiers(false),
+ SuppressTagKeyword(LO.CPlusPlus),
IncludeTagDefinition(false), SuppressScope(false),
SuppressUnwrittenScope(false), SuppressInitializers(false),
ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
SuppressTemplateArgsInCXXConstructors(false),
- Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false),
+ Bool(LO.Bool), Restrict(LO.C99),
+ Alignof(LO.CPlusPlus11), UnderscoreAlignof(LO.C11),
+ UseVoidForZeroParams(!LO.CPlusPlus),
+ TerseOutput(false), PolishForDeclaration(false),
Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
IncludeNewlines(true), MSVCFormatting(false) { }
- /// \brief What language we're printing.
- LangOptions LangOpts;
+ /// \brief 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 construct). This should not be used if a real LangOptions
+ /// object is available.
+ void adjustForCPlusPlus() {
+ SuppressTagKeyword = true;
+ Bool = true;
+ UseVoidForZeroParams = false;
+ }
/// \brief The number of spaces to use to indent each line.
unsigned Indentation : 8;
@@ -143,10 +156,23 @@ struct PrintingPolicy {
/// constructors.
unsigned SuppressTemplateArgsInCXXConstructors : 1;
- /// \brief Whether we can use 'bool' rather than '_Bool', even if the language
- /// doesn't actually have 'bool' (because, e.g., it is defined as a macro).
+ /// \brief Whether we can use 'bool' rather than '_Bool' (even if the language
+ /// doesn't actually have 'bool', because, e.g., it is defined as a macro).
unsigned Bool : 1;
+ /// \brief Whether we can use 'restrict' rather than '__restrict'.
+ unsigned Restrict : 1;
+
+ /// \brief Whether we can use 'alignof' rather than '__alignof'.
+ unsigned Alignof : 1;
+
+ /// \brief Whether we can use '_Alignof' rather than '__alignof'.
+ unsigned UnderscoreAlignof : 1;
+
+ /// \brief Whether we should use '(void)' rather than '()' for a function
+ /// prototype with zero parameters.
+ unsigned UseVoidForZeroParams : 1;
+
/// \brief Provide a 'terse' output.
///
/// For example, in this mode we don't print function bodies, class members,
diff --git a/clang/lib/AST/DeclarationName.cpp b/clang/lib/AST/DeclarationName.cpp
index 344a2389228..2a988e1d22d 100644
--- a/clang/lib/AST/DeclarationName.cpp
+++ b/clang/lib/AST/DeclarationName.cpp
@@ -135,7 +135,10 @@ int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
static void printCXXConstructorDestructorName(QualType ClassType,
raw_ostream &OS,
- const PrintingPolicy &Policy) {
+ PrintingPolicy Policy) {
+ // We know we're printing C++ here. Ensure we print types properly.
+ Policy.adjustForCPlusPlus();
+
if (const RecordType *ClassRec = ClassType->getAs<RecordType>()) {
OS << *ClassRec->getDecl();
return;
@@ -146,14 +149,7 @@ static void printCXXConstructorDestructorName(QualType ClassType,
return;
}
}
- if (!Policy.LangOpts.CPlusPlus) {
- // Passed policy is the default one from operator <<, use a C++ policy.
- LangOptions LO;
- LO.CPlusPlus = true;
- ClassType.print(OS, PrintingPolicy(LO));
- } else {
- ClassType.print(OS, Policy);
- }
+ ClassType.print(OS, Policy);
}
void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) {
@@ -206,15 +202,10 @@ void DeclarationName::print(raw_ostream &OS, const PrintingPolicy &Policy) {
OS << *Rec->getDecl();
return;
}
- if (!Policy.LangOpts.CPlusPlus) {
- // Passed policy is the default one from operator <<, use a C++ policy.
- LangOptions LO;
- LO.CPlusPlus = true;
- LO.Bool = true;
- Type.print(OS, PrintingPolicy(LO));
- } else {
- Type.print(OS, Policy);
- }
+ // We know we're printing C++ here, ensure we print 'bool' properly.
+ PrintingPolicy CXXPolicy = Policy;
+ CXXPolicy.adjustForCPlusPlus();
+ Type.print(OS, CXXPolicy);
return;
}
case DeclarationName::CXXUsingDirective:
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 0b3f9087909..0aa327da85e 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1397,9 +1397,9 @@ void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node){
OS << "sizeof";
break;
case UETT_AlignOf:
- if (Policy.LangOpts.CPlusPlus)
+ if (Policy.Alignof)
OS << "alignof";
- else if (Policy.LangOpts.C11)
+ else if (Policy.UnderscoreAlignof)
OS << "_Alignof";
else
OS << "__alignof";
@@ -1669,7 +1669,7 @@ void StmtPrinter::VisitNoInitExpr(NoInitExpr *Node) {
}
void StmtPrinter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *Node) {
- if (Policy.LangOpts.CPlusPlus) {
+ if (Node->getType()->getAsCXXRecordDecl()) {
OS << "/*implicit*/";
Node->getType().print(OS, Policy);
OS << "()";
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 7e04e81e8d1..29a4845d4a9 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -112,7 +112,8 @@ namespace {
};
}
-static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals, bool C99) {
+static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals,
+ bool HasRestrictKeyword) {
bool appendSpace = false;
if (TypeQuals & Qualifiers::Const) {
OS << "const";
@@ -125,7 +126,7 @@ static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals, bool C99) {
}
if (TypeQuals & Qualifiers::Restrict) {
if (appendSpace) OS << ' ';
- if (C99) {
+ if (HasRestrictKeyword) {
OS << "restrict";
} else {
OS << "__restrict";
@@ -439,7 +440,8 @@ void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T,
raw_ostream &OS) {
OS << '[';
if (T->getIndexTypeQualifiers().hasQualifiers()) {
- AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.LangOpts.C99);
+ AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(),
+ Policy.Restrict);
OS << ' ';
}
@@ -472,7 +474,7 @@ void TypePrinter::printVariableArrayAfter(const VariableArrayType *T,
raw_ostream &OS) {
OS << '[';
if (T->getIndexTypeQualifiers().hasQualifiers()) {
- AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.LangOpts.C99);
+ AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.Restrict);
OS << ' ';
}
@@ -672,7 +674,7 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
if (T->getNumParams())
OS << ", ";
OS << "...";
- } else if (T->getNumParams() == 0 && !Policy.LangOpts.CPlusPlus) {
+ } else if (T->getNumParams() == 0 && Policy.UseVoidForZeroParams) {
// Do not emit int() if we have a proto, emit 'int(void)'.
OS << "void";
}
@@ -746,7 +748,7 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
if (unsigned quals = T->getTypeQuals()) {
OS << ' ';
- AppendTypeQualList(OS, quals, Policy.LangOpts.C99);
+ AppendTypeQualList(OS, quals, Policy.Restrict);
}
switch (T->getRefQualifier()) {
@@ -947,13 +949,9 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
bool HasKindDecoration = false;
- // bool SuppressTagKeyword
- // = Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword;
-
// We don't print tags unless this is an elaborated type.
// In C, we just assume every RecordType is an elaborated type.
- if (!(Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword ||
- D->getTypedefNameForAnonDecl())) {
+ if (!Policy.SuppressTagKeyword && !D->getTypedefNameForAnonDecl()) {
HasKindDecoration = true;
OS << D->getKindName();
OS << ' ';
@@ -1590,7 +1588,7 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
unsigned quals = getCVRQualifiers();
if (quals) {
- AppendTypeQualList(OS, quals, Policy.LangOpts.C99);
+ AppendTypeQualList(OS, quals, Policy.Restrict);
addSpace = true;
}
if (hasUnaligned()) {
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 91445281673..8a3110c5153 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2661,7 +2661,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
bool AttrsLastTime = false;
ParsedAttributesWithRange attrs(AttrFactory);
// We use Sema's policy to get bool macros right.
- const PrintingPolicy &Policy = Actions.getPrintingPolicy();
+ PrintingPolicy Policy = Actions.getPrintingPolicy();
while (1) {
bool isInvalid = false;
bool isStorageClass = false;
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index b4692fca229..83ab2473702 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -52,13 +52,14 @@ ModuleLoader &Sema::getModuleLoader() const { return PP.getModuleLoader(); }
PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context,
const Preprocessor &PP) {
PrintingPolicy Policy = Context.getPrintingPolicy();
+ // Our printing policy is copied over the ASTContext printing policy whenever
+ // a diagnostic is emitted, so recompute it.
Policy.Bool = Context.getLangOpts().Bool;
if (!Policy.Bool) {
- if (const MacroInfo *
- BoolMacro = PP.getMacroInfo(&Context.Idents.get("bool"))) {
+ if (const MacroInfo *BoolMacro = PP.getMacroInfo(Context.getBoolName())) {
Policy.Bool = BoolMacro->isObjectLike() &&
- BoolMacro->getNumTokens() == 1 &&
- BoolMacro->getReplacementToken(0).is(tok::kw__Bool);
+ BoolMacro->getNumTokens() == 1 &&
+ BoolMacro->getReplacementToken(0).is(tok::kw__Bool);
}
}
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 3f5afab7bf5..ef14660135b 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -1517,7 +1517,6 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
ResultBuilder &Results) {
CodeCompletionAllocator &Allocator = Results.getAllocator();
CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
- PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
typedef CodeCompletionResult Result;
switch (CCC) {
diff --git a/clang/test/Analysis/initializers-cfg-output.cpp b/clang/test/Analysis/initializers-cfg-output.cpp
index db3c0fb9900..deefbef0773 100644
--- a/clang/test/Analysis/initializers-cfg-output.cpp
+++ b/clang/test/Analysis/initializers-cfg-output.cpp
@@ -61,7 +61,7 @@ class TestDelegating {
// CHECK: 6: B([B1.5]) (Base initializer)
// CHECK: 7: (CXXConstructExpr, class A)
// CHECK: 8: A([B1.7]) (Base initializer)
-// CHECK: 9: /*implicit*/int()
+// CHECK: 9: /*implicit*/(int)0
// CHECK: 10: i([B1.9]) (Member initializer)
// CHECK: 11: this
// CHECK: 12: [B1.11]->i
diff --git a/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp b/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp
index dc10e875d36..b425d916110 100644
--- a/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp
+++ b/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp
@@ -1077,7 +1077,7 @@ int testConsistencyNestedNormalReturn(bool value) {
// CHECK: 14: a([B1.13]) (Member initializer)
// CHECK: 15: ~B() (Temporary object destructor)
// CHECK: 16: ~A() (Temporary object destructor)
-// CHECK: 17: /*implicit*/int()
+// CHECK: 17: /*implicit*/(int)0
// CHECK: 18: b([B1.17]) (Member initializer)
// CHECK: Preds (1): B2
// CHECK: Succs (1): B0
diff --git a/clang/test/SemaCXX/member-pointer.cpp b/clang/test/SemaCXX/member-pointer.cpp
index f3adb95977a..ef76279c37e 100644
--- a/clang/test/SemaCXX/member-pointer.cpp
+++ b/clang/test/SemaCXX/member-pointer.cpp
@@ -323,3 +323,12 @@ namespace test8 {
.**(int A::**) 0; // expected-warning {{indirection of non-volatile null pointer will be deleted}} expected-note {{consider}}
}
}
+
+namespace PR27558 {
+ template<typename Args> struct A { void f(); };
+ template<typename Args> struct B : A<Args> {
+ using A<Args>::f;
+ B() { (void)&B<Args>::f; }
+ };
+ B<int> b;
+}
OpenPOWER on IntegriCloud