Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -2048,17 +2048,15 @@ unsigned SpellingIndex = getSpellingListIndex(); // For "#pragma unroll" and "#pragma nounroll" the string "unroll" or // "nounroll" is already emitted as the pragma name. - if (SpellingIndex == Pragma_nounroll) { - OS << "\n"; + if (SpellingIndex == Pragma_nounroll) return; - } else if (SpellingIndex == Pragma_unroll) { - OS << getValueString(Policy) << "\n"; + OS << getValueString(Policy); return; } assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling"); - OS << getOptionName(option) << getValueString(Policy) << "\n"; + OS << getOptionName(option) << getValueString(Policy); } // Return a string containing the loop hint argument including the Index: lib/AST/DeclPrinter.cpp =================================================================== --- lib/AST/DeclPrinter.cpp +++ lib/AST/DeclPrinter.cpp @@ -95,7 +95,7 @@ void PrintTemplateParameters(const TemplateParameterList *Params, const TemplateArgumentList *Args = nullptr); - void prettyPrintAttributes(Decl *D); + void prettyPrintAttributes(Decl *D, bool PrintPragmas = false); void printDeclType(QualType T, StringRef DeclName, bool Pack = false); }; } @@ -194,15 +194,27 @@ return Out; } -void DeclPrinter::prettyPrintAttributes(Decl *D) { +void DeclPrinter::prettyPrintAttributes(Decl *D, bool PrintPragmas) { if (Policy.PolishForDeclaration) return; - + if (D->hasAttrs()) { AttrVec &Attrs = D->getAttrs(); - for (AttrVec::const_iterator i=Attrs.begin(), e=Attrs.end(); i!=e; ++i) { - Attr *A = *i; - A->printPretty(Out, Policy); + for (auto *A : Attrs) { + switch (A->getKind()) { +#define ATTR(X) +#define PRAGMA_SPELLING_ATTR(X) case attr::X: +#include "clang/Basic/AttrList.inc" + if (PrintPragmas) { + A->printPretty(Out, Policy); + Indent(); + } + break; + default: + if (!PrintPragmas) + A->printPretty(Out, Policy); + break; + } } } } @@ -408,6 +420,10 @@ } void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { + if (!D->getDescribedFunctionTemplate() && + !D->isFunctionTemplateSpecialization()) + prettyPrintAttributes(D, /*PrintPragmas=*/true); + CXXConstructorDecl *CDecl = dyn_cast(D); CXXConversionDecl *ConversionDecl = dyn_cast(D); if (!Policy.SuppressSpecifiers) { @@ -643,6 +659,7 @@ } void DeclPrinter::VisitFieldDecl(FieldDecl *D) { + // FIXME: add printing of pragma attributes if required. if (!Policy.SuppressSpecifiers && D->isMutable()) Out << "mutable "; if (!Policy.SuppressSpecifiers && D->isModulePrivate()) @@ -672,6 +689,7 @@ } void DeclPrinter::VisitVarDecl(VarDecl *D) { + prettyPrintAttributes(D, /*PrintPragmas=*/true); if (!Policy.SuppressSpecifiers) { StorageClass SC = D->getStorageClass(); if (SC != SC_None) @@ -779,6 +797,7 @@ } void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { + // FIXME: add printing of pragma attributes if required. if (!Policy.SuppressSpecifiers && D->isModulePrivate()) Out << "__module_private__ "; Out << D->getKindName(); @@ -914,11 +933,13 @@ if (PrintInstantiation) { TemplateParameterList *Params = D->getTemplateParameters(); for (auto *I : D->specializations()) { + prettyPrintAttributes(I, /*PrintPragmas=*/true); PrintTemplateParameters(Params, I->getTemplateSpecializationArgs()); Visit(I); } } + prettyPrintAttributes(D->getTemplatedDecl(), /*PrintPragmas=*/true); return VisitRedeclarableTemplateDecl(D); } Index: test/SemaCXX/pragma-init_seg.cpp =================================================================== --- test/SemaCXX/pragma-init_seg.cpp +++ test/SemaCXX/pragma-init_seg.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -triple x86_64-pc-win32 +// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -triple x86_64-pc-win32 -ast-print | FileCheck %s // RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions %s -triple i386-apple-darwin13.3.0 #ifndef __APPLE__ @@ -18,4 +18,6 @@ #endif int f(); +// CHECK: #pragma init_seg (.CRT$XCC) +// CHECK-NEXT: int x = f() __declspec(thread); int __declspec(thread) x = f(); // expected-error {{initializer for thread-local variable must be a constant expression}} Index: utils/TableGen/ClangAttrEmitter.cpp =================================================================== --- utils/TableGen/ClangAttrEmitter.cpp +++ utils/TableGen/ClangAttrEmitter.cpp @@ -1180,6 +1180,7 @@ if (Variety == "Pragma") { OS << " \";\n"; OS << " printPrettyPragma(OS, Policy);\n"; + OS << " OS << \"\\n\";"; OS << " break;\n"; OS << " }\n"; continue;