2009-05-30 08:08:05 +08:00
|
|
|
//===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2012-12-20 10:09:13 +08:00
|
|
|
// This file implements the Decl::print method, which pretty prints the
|
2009-05-30 08:08:05 +08:00
|
|
|
// AST back out to C/Objective-C/C++/Objective-C++ code.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/AST/ASTContext.h"
|
2012-12-01 23:09:41 +08:00
|
|
|
#include "clang/AST/Attr.h"
|
2009-05-30 08:08:05 +08:00
|
|
|
#include "clang/AST/Decl.h"
|
|
|
|
#include "clang/AST/DeclCXX.h"
|
|
|
|
#include "clang/AST/DeclObjC.h"
|
2012-12-01 23:09:41 +08:00
|
|
|
#include "clang/AST/DeclVisitor.h"
|
2009-05-30 08:08:05 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
Rework base and member initialization in constructors, with several
(necessarily simultaneous) changes:
- CXXBaseOrMemberInitializer now contains only a single initializer
rather than a set of initialiation arguments + a constructor. The
single initializer covers all aspects of initialization, including
constructor calls as necessary but also cleanup of temporaries
created by the initializer (which we never handled
before!).
- Rework + simplify code generation for CXXBaseOrMemberInitializers,
since we can now just emit the initializer as an initializer.
- Switched base and member initialization over to the new
initialization code (InitializationSequence), so that it
- Improved diagnostics for the new initialization code when
initializing bases and members, to match the diagnostics produced
by the previous (special-purpose) code.
- Simplify the representation of type-checked constructor initializers in
templates; instead of keeping the fully-type-checked AST, which is
rather hard to undo at template instantiation time, throw away the
type-checked AST and store the raw expressions in the AST. This
simplifies instantiation, but loses a little but of information in
the AST.
- When type-checking implicit base or member initializers within a
dependent context, don't add the generated initializers into the
AST, because they'll look like they were explicit.
- Record in CXXConstructExpr when the constructor call is to
initialize a base class, so that CodeGen does not have to infer it
from context. This ensures that we call the right kind of
constructor.
There are also a few "opportunity" fixes here that were needed to not
regress, for example:
- Diagnose default-initialization of a const-qualified class that
does not have a user-declared default constructor. We had this
diagnostic specifically for bases and members, but missed it for
variables. That's fixed now.
- When defining the implicit constructors, destructor, and
copy-assignment operator, set the CurContext to that constructor
when we're defining the body.
llvm-svn: 94952
2010-01-31 17:12:51 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
2009-05-30 08:08:05 +08:00
|
|
|
#include "clang/AST/PrettyPrinter.h"
|
2011-12-03 07:23:56 +08:00
|
|
|
#include "clang/Basic/Module.h"
|
2009-05-30 08:08:05 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
namespace {
|
2009-11-29 03:03:38 +08:00
|
|
|
class DeclPrinter : public DeclVisitor<DeclPrinter> {
|
2011-07-23 18:55:15 +08:00
|
|
|
raw_ostream &Out;
|
2009-05-30 08:08:05 +08:00
|
|
|
PrintingPolicy Policy;
|
2017-08-17 21:41:55 +08:00
|
|
|
const ASTContext &Context;
|
2009-05-30 08:08:05 +08:00
|
|
|
unsigned Indentation;
|
2011-07-28 08:19:05 +08:00
|
|
|
bool PrintInstantiation;
|
2009-05-30 08:08:05 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
raw_ostream& Indent() { return Indent(Indentation); }
|
|
|
|
raw_ostream& Indent(unsigned Indentation);
|
|
|
|
void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls);
|
2009-05-30 08:08:05 +08:00
|
|
|
|
2009-08-29 06:39:52 +08:00
|
|
|
void Print(AccessSpecifier AS);
|
2017-11-16 09:31:27 +08:00
|
|
|
void PrintConstructorInitializers(CXXConstructorDecl *CDecl,
|
|
|
|
std::string &Proto);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2015-06-20 02:14:38 +08:00
|
|
|
/// Print an Objective-C method type in parentheses.
|
|
|
|
///
|
|
|
|
/// \param Quals The Objective-C declaration qualifiers.
|
|
|
|
/// \param T The type to print.
|
|
|
|
void PrintObjCMethodType(ASTContext &Ctx, Decl::ObjCDeclQualifier Quals,
|
|
|
|
QualType T);
|
|
|
|
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
void PrintObjCTypeParams(ObjCTypeParamList *Params);
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
public:
|
2012-08-16 11:56:14 +08:00
|
|
|
DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
|
2017-08-17 21:41:55 +08:00
|
|
|
const ASTContext &Context, unsigned Indentation = 0,
|
|
|
|
bool PrintInstantiation = false)
|
|
|
|
: Out(Out), Policy(Policy), Context(Context), Indentation(Indentation),
|
|
|
|
PrintInstantiation(PrintInstantiation) {}
|
2009-05-30 08:08:05 +08:00
|
|
|
|
|
|
|
void VisitDeclContext(DeclContext *DC, bool Indent = true);
|
|
|
|
|
|
|
|
void VisitTranslationUnitDecl(TranslationUnitDecl *D);
|
|
|
|
void VisitTypedefDecl(TypedefDecl *D);
|
2011-04-15 22:24:37 +08:00
|
|
|
void VisitTypeAliasDecl(TypeAliasDecl *D);
|
2009-05-30 08:08:05 +08:00
|
|
|
void VisitEnumDecl(EnumDecl *D);
|
|
|
|
void VisitRecordDecl(RecordDecl *D);
|
|
|
|
void VisitEnumConstantDecl(EnumConstantDecl *D);
|
2013-02-23 01:15:32 +08:00
|
|
|
void VisitEmptyDecl(EmptyDecl *D);
|
2009-05-30 08:08:05 +08:00
|
|
|
void VisitFunctionDecl(FunctionDecl *D);
|
2012-12-05 08:38:44 +08:00
|
|
|
void VisitFriendDecl(FriendDecl *D);
|
2009-05-30 08:08:05 +08:00
|
|
|
void VisitFieldDecl(FieldDecl *D);
|
|
|
|
void VisitVarDecl(VarDecl *D);
|
2011-02-18 04:34:02 +08:00
|
|
|
void VisitLabelDecl(LabelDecl *D);
|
2009-05-30 08:08:05 +08:00
|
|
|
void VisitParmVarDecl(ParmVarDecl *D);
|
|
|
|
void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
|
2011-12-03 07:23:56 +08:00
|
|
|
void VisitImportDecl(ImportDecl *D);
|
2011-03-17 02:37:27 +08:00
|
|
|
void VisitStaticAssertDecl(StaticAssertDecl *D);
|
2009-05-30 14:58:37 +08:00
|
|
|
void VisitNamespaceDecl(NamespaceDecl *D);
|
2009-05-30 14:31:56 +08:00
|
|
|
void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
|
2009-05-30 14:48:27 +08:00
|
|
|
void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
|
2009-05-30 14:58:37 +08:00
|
|
|
void VisitCXXRecordDecl(CXXRecordDecl *D);
|
2009-05-30 08:08:05 +08:00
|
|
|
void VisitLinkageSpecDecl(LinkageSpecDecl *D);
|
2011-04-15 21:38:57 +08:00
|
|
|
void VisitTemplateDecl(const TemplateDecl *D);
|
2011-07-28 08:19:05 +08:00
|
|
|
void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
|
|
|
|
void VisitClassTemplateDecl(ClassTemplateDecl *D);
|
2016-11-10 16:49:37 +08:00
|
|
|
void VisitClassTemplateSpecializationDecl(
|
|
|
|
ClassTemplateSpecializationDecl *D);
|
|
|
|
void VisitClassTemplatePartialSpecializationDecl(
|
|
|
|
ClassTemplatePartialSpecializationDecl *D);
|
2009-05-30 08:08:05 +08:00
|
|
|
void VisitObjCMethodDecl(ObjCMethodDecl *D);
|
|
|
|
void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
|
|
|
|
void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
|
|
|
|
void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
|
|
|
|
void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
|
|
|
|
void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
|
|
|
|
void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
|
|
|
|
void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
|
|
|
|
void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
|
2009-11-18 10:36:19 +08:00
|
|
|
void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
|
|
|
|
void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
|
2009-08-29 03:16:39 +08:00
|
|
|
void VisitUsingDecl(UsingDecl *D);
|
2009-11-17 13:59:44 +08:00
|
|
|
void VisitUsingShadowDecl(UsingShadowDecl *D);
|
2013-03-22 14:34:35 +08:00
|
|
|
void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
|
2016-03-03 13:21:39 +08:00
|
|
|
void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
|
2016-02-11 13:35:55 +08:00
|
|
|
void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
|
2011-07-28 08:19:05 +08:00
|
|
|
|
2016-11-10 16:49:37 +08:00
|
|
|
void printTemplateParameters(const TemplateParameterList *Params);
|
|
|
|
void printTemplateArguments(const TemplateArgumentList &Args,
|
|
|
|
const TemplateParameterList *Params = nullptr);
|
2011-11-20 03:22:57 +08:00
|
|
|
void prettyPrintAttributes(Decl *D);
|
2015-10-12 14:59:48 +08:00
|
|
|
void prettyPrintPragmas(Decl *D);
|
2014-07-23 11:17:06 +08:00
|
|
|
void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
|
2009-05-30 08:08:05 +08:00
|
|
|
};
|
2015-06-23 07:07:51 +08:00
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
|
2011-07-28 08:19:05 +08:00
|
|
|
void Decl::print(raw_ostream &Out, unsigned Indentation,
|
|
|
|
bool PrintInstantiation) const {
|
2011-09-28 06:38:19 +08:00
|
|
|
print(Out, getASTContext().getPrintingPolicy(), Indentation, PrintInstantiation);
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy,
|
2011-07-28 08:19:05 +08:00
|
|
|
unsigned Indentation, bool PrintInstantiation) const {
|
2017-08-17 21:41:55 +08:00
|
|
|
DeclPrinter Printer(Out, Policy, getASTContext(), Indentation,
|
|
|
|
PrintInstantiation);
|
2009-09-27 05:58:53 +08:00
|
|
|
Printer.Visit(const_cast<Decl*>(this));
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
2009-05-30 12:20:30 +08:00
|
|
|
static QualType GetBaseType(QualType T) {
|
|
|
|
// FIXME: This should be on the Type class!
|
|
|
|
QualType BaseType = T;
|
|
|
|
while (!BaseType->isSpecifierType()) {
|
2018-01-18 03:29:39 +08:00
|
|
|
if (const PointerType *PTy = BaseType->getAs<PointerType>())
|
2009-05-30 12:20:30 +08:00
|
|
|
BaseType = PTy->getPointeeType();
|
2012-10-12 04:58:14 +08:00
|
|
|
else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>())
|
|
|
|
BaseType = BPy->getPointeeType();
|
2009-05-30 12:20:30 +08:00
|
|
|
else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType))
|
|
|
|
BaseType = ATy->getElementType();
|
2009-09-22 07:43:11 +08:00
|
|
|
else if (const FunctionType* FTy = BaseType->getAs<FunctionType>())
|
2014-01-26 00:55:45 +08:00
|
|
|
BaseType = FTy->getReturnType();
|
2009-09-22 07:43:11 +08:00
|
|
|
else if (const VectorType *VTy = BaseType->getAs<VectorType>())
|
2009-07-02 07:58:14 +08:00
|
|
|
BaseType = VTy->getElementType();
|
2012-08-08 11:47:15 +08:00
|
|
|
else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>())
|
|
|
|
BaseType = RTy->getPointeeType();
|
2016-07-09 00:04:22 +08:00
|
|
|
else if (const AutoType *ATy = BaseType->getAs<AutoType>())
|
|
|
|
BaseType = ATy->getDeducedType();
|
2018-01-18 03:29:39 +08:00
|
|
|
else if (const ParenType *PTy = BaseType->getAs<ParenType>())
|
|
|
|
BaseType = PTy->desugar();
|
2009-05-30 12:20:30 +08:00
|
|
|
else
|
2018-01-18 03:29:39 +08:00
|
|
|
// This must be a syntax error.
|
|
|
|
break;
|
2009-05-30 12:20:30 +08:00
|
|
|
}
|
|
|
|
return BaseType;
|
|
|
|
}
|
|
|
|
|
|
|
|
static QualType getDeclType(Decl* D) {
|
2011-04-15 22:24:37 +08:00
|
|
|
if (TypedefNameDecl* TDD = dyn_cast<TypedefNameDecl>(D))
|
2009-05-30 12:20:30 +08:00
|
|
|
return TDD->getUnderlyingType();
|
|
|
|
if (ValueDecl* VD = dyn_cast<ValueDecl>(D))
|
|
|
|
return VD->getType();
|
|
|
|
return QualType();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Decl::printGroup(Decl** Begin, unsigned NumDecls,
|
2011-07-23 18:55:15 +08:00
|
|
|
raw_ostream &Out, const PrintingPolicy &Policy,
|
2009-05-30 12:20:30 +08:00
|
|
|
unsigned Indentation) {
|
|
|
|
if (NumDecls == 1) {
|
2009-06-30 10:35:04 +08:00
|
|
|
(*Begin)->print(Out, Policy, Indentation);
|
2009-05-30 12:20:30 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Decl** End = Begin + NumDecls;
|
|
|
|
TagDecl* TD = dyn_cast<TagDecl>(*Begin);
|
|
|
|
if (TD)
|
|
|
|
++Begin;
|
|
|
|
|
|
|
|
PrintingPolicy SubPolicy(Policy);
|
|
|
|
|
|
|
|
bool isFirst = true;
|
|
|
|
for ( ; Begin != End; ++Begin) {
|
|
|
|
if (isFirst) {
|
2016-03-19 05:35:59 +08:00
|
|
|
if(TD)
|
|
|
|
SubPolicy.IncludeTagDefinition = true;
|
2009-05-30 12:20:30 +08:00
|
|
|
SubPolicy.SuppressSpecifiers = false;
|
|
|
|
isFirst = false;
|
|
|
|
} else {
|
|
|
|
if (!isFirst) Out << ", ";
|
2016-03-19 05:35:59 +08:00
|
|
|
SubPolicy.IncludeTagDefinition = false;
|
2009-05-30 12:20:30 +08:00
|
|
|
SubPolicy.SuppressSpecifiers = true;
|
|
|
|
}
|
|
|
|
|
2009-06-30 10:35:04 +08:00
|
|
|
(*Begin)->print(Out, SubPolicy, Indentation);
|
2009-05-30 12:20:30 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-04 21:47:14 +08:00
|
|
|
LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const {
|
2009-12-10 01:27:46 +08:00
|
|
|
// Get the translation unit
|
|
|
|
const DeclContext *DC = this;
|
|
|
|
while (!DC->isTranslationUnit())
|
|
|
|
DC = DC->getParent();
|
|
|
|
|
|
|
|
ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
|
2017-08-17 21:41:55 +08:00
|
|
|
DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), Ctx, 0);
|
2009-12-10 01:27:46 +08:00
|
|
|
Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false);
|
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
|
2009-11-21 17:12:06 +08:00
|
|
|
for (unsigned i = 0; i != Indentation; ++i)
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << " ";
|
|
|
|
return Out;
|
|
|
|
}
|
|
|
|
|
2011-11-20 03:22:57 +08:00
|
|
|
void DeclPrinter::prettyPrintAttributes(Decl *D) {
|
2012-12-20 07:36:00 +08:00
|
|
|
if (Policy.PolishForDeclaration)
|
2012-10-18 05:58:03 +08:00
|
|
|
return;
|
2015-10-12 14:59:48 +08:00
|
|
|
|
2011-11-20 03:22:57 +08:00
|
|
|
if (D->hasAttrs()) {
|
|
|
|
AttrVec &Attrs = D->getAttrs();
|
2015-10-12 14:59:48 +08:00
|
|
|
for (auto *A : Attrs) {
|
2018-05-16 06:16:47 +08:00
|
|
|
if (A->isInherited() || A->isImplicit())
|
[AST] Print correct tag decl for tag specifier
For example, given:
void fn() {
struct T *p0;
struct T { int i; } *p1;
}
-ast-print produced:
void fn() {
struct T { int i; } *p0;
struct T { int i; } *p1;
}
Compiling that fails with a redefinition error.
Given:
void fn() {
struct T *p0;
struct __attribute__((deprecated)) T *p1;
}
-ast-print dropped the attribute.
Details:
For a tag specifier (that is, struct/union/class/enum used as a type
specifier in a declaration) that was also a tag declaration (that is,
first occurrence of the tag) or tag redeclaration (that is, later
occurrence that specifies attributes or a member list), clang printed
the tag specifier as either (1) the full tag definition if one
existed, or (2) the first tag declaration otherwise. Redefinition
errors were sometimes introduced, as in the first example above. Even
when that was impossible because no member list was ever specified,
attributes were sometimes lost, thus changing semantics and
diagnostics, as in the second example above.
This patch fixes a major culprit for these problems. It does so by
creating an ElaboratedType with a new OwnedDecl member wherever an
occurrence of a tag type is a (re)declaration of that tag type.
PrintingPolicy's IncludeTagDefinition used to trigger printing of the
member list, attributes, etc. for a tag specifier by using a tag
(re)declaration selected as described above. Now, it triggers the
same thing except it uses the tag (re)declaration stored in the
OwnedDecl. Of course, other tooling can now make use of the new
OwnedDecl as well.
Also, to be more faithful to the original source, this patch
suppresses printing of attributes inherited from previous
declarations.
Reviewed by: rsmith, aaron.ballman
Differential Revision: https://reviews.llvm.org/D45463
llvm-svn: 332281
2018-05-15 03:36:45 +08:00
|
|
|
continue;
|
2015-10-12 14:59:48 +08:00
|
|
|
switch (A->getKind()) {
|
|
|
|
#define ATTR(X)
|
|
|
|
#define PRAGMA_SPELLING_ATTR(X) case attr::X:
|
|
|
|
#include "clang/Basic/AttrList.inc"
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
A->printPretty(Out, Policy);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::prettyPrintPragmas(Decl *D) {
|
|
|
|
if (Policy.PolishForDeclaration)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (D->hasAttrs()) {
|
|
|
|
AttrVec &Attrs = D->getAttrs();
|
|
|
|
for (auto *A : Attrs) {
|
|
|
|
switch (A->getKind()) {
|
|
|
|
#define ATTR(X)
|
|
|
|
#define PRAGMA_SPELLING_ATTR(X) case attr::X:
|
|
|
|
#include "clang/Basic/AttrList.inc"
|
|
|
|
A->printPretty(Out, Policy);
|
|
|
|
Indent();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2011-11-20 03:22:57 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-23 11:17:06 +08:00
|
|
|
void DeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) {
|
|
|
|
// Normally, a PackExpansionType is written as T[3]... (for instance, as a
|
|
|
|
// template argument), but if it is the type of a declaration, the ellipsis
|
|
|
|
// is placed before the name being declared.
|
|
|
|
if (auto *PET = T->getAs<PackExpansionType>()) {
|
|
|
|
Pack = true;
|
|
|
|
T = PET->getPattern();
|
|
|
|
}
|
2016-03-19 05:35:59 +08:00
|
|
|
T.print(Out, Policy, (Pack ? "..." : "") + DeclName, Indentation);
|
2014-07-23 11:17:06 +08:00
|
|
|
}
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
|
2009-05-30 12:20:30 +08:00
|
|
|
this->Indent();
|
2009-06-30 10:35:04 +08:00
|
|
|
Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
|
2009-05-30 12:20:30 +08:00
|
|
|
Out << ";\n";
|
|
|
|
Decls.clear();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-08-29 06:39:52 +08:00
|
|
|
void DeclPrinter::Print(AccessSpecifier AS) {
|
|
|
|
switch(AS) {
|
2011-09-24 04:26:49 +08:00
|
|
|
case AS_none: llvm_unreachable("No access specifier!");
|
2009-08-29 06:39:52 +08:00
|
|
|
case AS_public: Out << "public"; break;
|
|
|
|
case AS_protected: Out << "protected"; break;
|
2010-06-05 13:09:32 +08:00
|
|
|
case AS_private: Out << "private"; break;
|
2009-08-29 06:39:52 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-16 09:31:27 +08:00
|
|
|
void DeclPrinter::PrintConstructorInitializers(CXXConstructorDecl *CDecl,
|
|
|
|
std::string &Proto) {
|
|
|
|
bool HasInitializerList = false;
|
|
|
|
for (const auto *BMInitializer : CDecl->inits()) {
|
|
|
|
if (BMInitializer->isInClassMemberInitializer())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!HasInitializerList) {
|
|
|
|
Proto += " : ";
|
|
|
|
Out << Proto;
|
|
|
|
Proto.clear();
|
|
|
|
HasInitializerList = true;
|
|
|
|
} else
|
|
|
|
Out << ", ";
|
|
|
|
|
|
|
|
if (BMInitializer->isAnyMemberInitializer()) {
|
|
|
|
FieldDecl *FD = BMInitializer->getAnyMember();
|
|
|
|
Out << *FD;
|
|
|
|
} else {
|
|
|
|
Out << QualType(BMInitializer->getBaseClass(), 0).getAsString(Policy);
|
|
|
|
}
|
|
|
|
|
|
|
|
Out << "(";
|
|
|
|
if (!BMInitializer->getInit()) {
|
|
|
|
// Nothing to print
|
|
|
|
} else {
|
|
|
|
Expr *Init = BMInitializer->getInit();
|
|
|
|
if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
|
|
|
|
Init = Tmp->getSubExpr();
|
|
|
|
|
|
|
|
Init = Init->IgnoreParens();
|
|
|
|
|
|
|
|
Expr *SimpleInit = nullptr;
|
|
|
|
Expr **Args = nullptr;
|
|
|
|
unsigned NumArgs = 0;
|
|
|
|
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
|
|
|
|
Args = ParenList->getExprs();
|
|
|
|
NumArgs = ParenList->getNumExprs();
|
|
|
|
} else if (CXXConstructExpr *Construct =
|
|
|
|
dyn_cast<CXXConstructExpr>(Init)) {
|
|
|
|
Args = Construct->getArgs();
|
|
|
|
NumArgs = Construct->getNumArgs();
|
|
|
|
} else
|
|
|
|
SimpleInit = Init;
|
|
|
|
|
|
|
|
if (SimpleInit)
|
|
|
|
SimpleInit->printPretty(Out, nullptr, Policy, Indentation);
|
|
|
|
else {
|
|
|
|
for (unsigned I = 0; I != NumArgs; ++I) {
|
|
|
|
assert(Args[I] != nullptr && "Expected non-null Expr");
|
|
|
|
if (isa<CXXDefaultArgExpr>(Args[I]))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (I)
|
|
|
|
Out << ", ";
|
|
|
|
Args[I]->printPretty(Out, nullptr, Policy, Indentation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
if (BMInitializer->isPackExpansion())
|
|
|
|
Out << "...";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// Common C declarations
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
|
2012-08-22 01:36:32 +08:00
|
|
|
if (Policy.TerseOutput)
|
2012-08-21 07:39:06 +08:00
|
|
|
return;
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (Indent)
|
|
|
|
Indentation += Policy.Indentation;
|
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<Decl*, 2> Decls;
|
2009-06-30 10:36:12 +08:00
|
|
|
for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
|
2009-05-30 08:08:05 +08:00
|
|
|
D != DEnd; ++D) {
|
2010-07-30 08:47:46 +08:00
|
|
|
|
|
|
|
// Don't print ObjCIvarDecls, as they are printed when visiting the
|
|
|
|
// containing ObjCInterfaceDecl.
|
|
|
|
if (isa<ObjCIvarDecl>(*D))
|
|
|
|
continue;
|
|
|
|
|
2012-12-20 10:09:13 +08:00
|
|
|
// Skip over implicit declarations in pretty-printing mode.
|
|
|
|
if (D->isImplicit())
|
|
|
|
continue;
|
|
|
|
|
2016-11-10 16:49:37 +08:00
|
|
|
// Don't print implicit specializations, as they are printed when visiting
|
|
|
|
// corresponding templates.
|
|
|
|
if (auto FD = dyn_cast<FunctionDecl>(*D))
|
|
|
|
if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation &&
|
|
|
|
!isa<ClassTemplateSpecializationDecl>(DC))
|
|
|
|
continue;
|
|
|
|
|
2018-05-15 08:44:14 +08:00
|
|
|
// The next bits of code handle stuff like "struct {int x;} a,b"; we're
|
2009-05-30 12:20:30 +08:00
|
|
|
// forced to merge the declarations because there's no other way to
|
2018-05-15 08:44:14 +08:00
|
|
|
// refer to the struct in question. When that struct is named instead, we
|
|
|
|
// also need to merge to avoid splitting off a stand-alone struct
|
|
|
|
// declaration that produces the warning ext_no_declarators in some
|
|
|
|
// contexts.
|
|
|
|
//
|
|
|
|
// This limited merging is safe without a bunch of other checks because it
|
|
|
|
// only merges declarations directly referring to the tag, not typedefs.
|
2009-05-30 12:20:30 +08:00
|
|
|
//
|
|
|
|
// Check whether the current declaration should be grouped with a previous
|
2018-05-15 08:44:14 +08:00
|
|
|
// non-free-standing tag declaration.
|
2009-05-30 12:20:30 +08:00
|
|
|
QualType CurDeclType = getDeclType(*D);
|
|
|
|
if (!Decls.empty() && !CurDeclType.isNull()) {
|
|
|
|
QualType BaseType = GetBaseType(CurDeclType);
|
2018-05-15 08:44:14 +08:00
|
|
|
if (!BaseType.isNull() && isa<ElaboratedType>(BaseType) &&
|
|
|
|
cast<ElaboratedType>(BaseType)->getOwnedTagDecl() == Decls[0]) {
|
2009-05-30 12:20:30 +08:00
|
|
|
Decls.push_back(*D);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we have a merged group waiting to be handled, handle it now.
|
|
|
|
if (!Decls.empty())
|
|
|
|
ProcessDeclGroup(Decls);
|
|
|
|
|
2018-05-15 08:44:14 +08:00
|
|
|
// If the current declaration is not a free standing declaration, save it
|
2009-05-30 12:20:30 +08:00
|
|
|
// so we can merge it with the subsequent declaration(s) using it.
|
2018-05-15 08:44:14 +08:00
|
|
|
if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->isFreeStanding()) {
|
2009-05-30 12:20:30 +08:00
|
|
|
Decls.push_back(*D);
|
|
|
|
continue;
|
|
|
|
}
|
2010-06-05 13:09:32 +08:00
|
|
|
|
|
|
|
if (isa<AccessSpecDecl>(*D)) {
|
|
|
|
Indentation -= Policy.Indentation;
|
|
|
|
this->Indent();
|
|
|
|
Print(D->getAccess());
|
|
|
|
Out << ":\n";
|
|
|
|
Indentation += Policy.Indentation;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
this->Indent();
|
|
|
|
Visit(*D);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
// FIXME: Need to be able to tell the DeclPrinter when
|
2014-05-07 17:53:02 +08:00
|
|
|
const char *Terminator = nullptr;
|
2016-03-03 13:21:39 +08:00
|
|
|
if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D))
|
2014-05-07 17:53:02 +08:00
|
|
|
Terminator = nullptr;
|
2016-10-31 13:11:12 +08:00
|
|
|
else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody())
|
2014-05-07 17:53:02 +08:00
|
|
|
Terminator = nullptr;
|
2016-11-10 16:49:37 +08:00
|
|
|
else if (auto FD = dyn_cast<FunctionDecl>(*D)) {
|
|
|
|
if (FD->isThisDeclarationADefinition())
|
|
|
|
Terminator = nullptr;
|
|
|
|
else
|
|
|
|
Terminator = ";";
|
|
|
|
} else if (auto TD = dyn_cast<FunctionTemplateDecl>(*D)) {
|
|
|
|
if (TD->getTemplatedDecl()->isThisDeclarationADefinition())
|
|
|
|
Terminator = nullptr;
|
|
|
|
else
|
|
|
|
Terminator = ";";
|
|
|
|
} else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) ||
|
2009-09-09 23:08:12 +08:00
|
|
|
isa<ObjCImplementationDecl>(*D) ||
|
2009-05-30 08:56:08 +08:00
|
|
|
isa<ObjCInterfaceDecl>(*D) ||
|
|
|
|
isa<ObjCProtocolDecl>(*D) ||
|
|
|
|
isa<ObjCCategoryImplDecl>(*D) ||
|
|
|
|
isa<ObjCCategoryDecl>(*D))
|
2014-05-07 17:53:02 +08:00
|
|
|
Terminator = nullptr;
|
2009-05-30 08:08:05 +08:00
|
|
|
else if (isa<EnumConstantDecl>(*D)) {
|
|
|
|
DeclContext::decl_iterator Next = D;
|
|
|
|
++Next;
|
|
|
|
if (Next != DEnd)
|
|
|
|
Terminator = ",";
|
|
|
|
} else
|
|
|
|
Terminator = ";";
|
|
|
|
|
|
|
|
if (Terminator)
|
|
|
|
Out << Terminator;
|
2016-11-10 16:49:37 +08:00
|
|
|
if (!Policy.TerseOutput &&
|
|
|
|
((isa<FunctionDecl>(*D) &&
|
|
|
|
cast<FunctionDecl>(*D)->doesThisDeclarationHaveABody()) ||
|
|
|
|
(isa<FunctionTemplateDecl>(*D) &&
|
|
|
|
cast<FunctionTemplateDecl>(*D)->getTemplatedDecl()->doesThisDeclarationHaveABody())))
|
|
|
|
; // StmtPrinter already added '\n' after CompoundStmt.
|
|
|
|
else
|
|
|
|
Out << "\n";
|
2016-04-06 19:38:59 +08:00
|
|
|
|
|
|
|
// Declare target attribute is special one, natural spelling for the pragma
|
|
|
|
// assumes "ending" construct so print it here.
|
|
|
|
if (D->hasAttr<OMPDeclareTargetDeclAttr>())
|
|
|
|
Out << "#pragma omp end declare target\n";
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
2009-05-30 12:20:30 +08:00
|
|
|
if (!Decls.empty())
|
|
|
|
ProcessDeclGroup(Decls);
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (Indent)
|
|
|
|
Indentation -= Policy.Indentation;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
|
|
|
|
VisitDeclContext(D, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
|
2011-09-09 10:06:17 +08:00
|
|
|
if (!Policy.SuppressSpecifiers) {
|
2009-05-30 12:20:30 +08:00
|
|
|
Out << "typedef ";
|
2011-09-09 10:06:17 +08:00
|
|
|
|
|
|
|
if (D->isModulePrivate())
|
|
|
|
Out << "__module_private__ ";
|
|
|
|
}
|
2016-03-19 05:35:59 +08:00
|
|
|
QualType Ty = D->getTypeSourceInfo()->getType();
|
|
|
|
Ty.print(Out, Policy, D->getName(), Indentation);
|
2011-11-20 03:22:57 +08:00
|
|
|
prettyPrintAttributes(D);
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
2011-04-15 22:24:37 +08:00
|
|
|
void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
|
2013-06-20 20:46:19 +08:00
|
|
|
Out << "using " << *D;
|
|
|
|
prettyPrintAttributes(D);
|
|
|
|
Out << " = " << D->getTypeSourceInfo()->getType().getAsString(Policy);
|
2011-04-15 22:24:37 +08:00
|
|
|
}
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
|
2011-09-09 10:06:17 +08:00
|
|
|
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
|
|
|
|
Out << "__module_private__ ";
|
2018-04-24 22:50:23 +08:00
|
|
|
Out << "enum";
|
2010-12-04 02:54:17 +08:00
|
|
|
if (D->isScoped()) {
|
|
|
|
if (D->isScopedUsingClassTag())
|
2018-04-24 22:50:23 +08:00
|
|
|
Out << " class";
|
2010-12-04 02:54:17 +08:00
|
|
|
else
|
2018-04-24 22:50:23 +08:00
|
|
|
Out << " struct";
|
2010-12-04 02:54:17 +08:00
|
|
|
}
|
2018-04-24 22:50:23 +08:00
|
|
|
|
|
|
|
prettyPrintAttributes(D);
|
|
|
|
|
|
|
|
Out << ' ' << *D;
|
2010-12-02 00:01:08 +08:00
|
|
|
|
2016-11-04 14:03:34 +08:00
|
|
|
if (D->isFixed() && D->getASTContext().getLangOpts().CPlusPlus11)
|
2012-05-05 12:20:37 +08:00
|
|
|
Out << " : " << D->getIntegerType().stream(Policy);
|
2010-12-02 00:01:08 +08:00
|
|
|
|
2011-10-07 14:10:15 +08:00
|
|
|
if (D->isCompleteDefinition()) {
|
2010-12-02 00:01:08 +08:00
|
|
|
Out << " {\n";
|
|
|
|
VisitDeclContext(D);
|
|
|
|
Indent() << "}";
|
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
|
2011-09-09 10:06:17 +08:00
|
|
|
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
|
|
|
|
Out << "__module_private__ ";
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << D->getKindName();
|
2014-09-16 00:45:30 +08:00
|
|
|
|
|
|
|
prettyPrintAttributes(D);
|
|
|
|
|
2010-04-17 17:33:03 +08:00
|
|
|
if (D->getIdentifier())
|
2011-10-15 02:45:37 +08:00
|
|
|
Out << ' ' << *D;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-10-07 14:10:15 +08:00
|
|
|
if (D->isCompleteDefinition()) {
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << " {\n";
|
|
|
|
VisitDeclContext(D);
|
|
|
|
Indent() << "}";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
|
2011-10-15 02:45:37 +08:00
|
|
|
Out << *D;
|
2017-01-20 11:33:42 +08:00
|
|
|
prettyPrintAttributes(D);
|
2009-05-30 08:08:05 +08:00
|
|
|
if (Expr *Init = D->getInitExpr()) {
|
|
|
|
Out << " = ";
|
2017-08-17 21:41:55 +08:00
|
|
|
Init->printPretty(Out, nullptr, Policy, Indentation, &Context);
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
2015-10-12 14:59:48 +08:00
|
|
|
if (!D->getDescribedFunctionTemplate() &&
|
|
|
|
!D->isFunctionTemplateSpecialization())
|
|
|
|
prettyPrintPragmas(D);
|
|
|
|
|
2016-11-10 16:49:37 +08:00
|
|
|
if (D->isFunctionTemplateSpecialization())
|
|
|
|
Out << "template<> ";
|
2017-04-18 23:12:34 +08:00
|
|
|
else if (!D->getDescribedFunctionTemplate()) {
|
|
|
|
for (unsigned I = 0, NumTemplateParams = D->getNumTemplateParameterLists();
|
|
|
|
I < NumTemplateParams; ++I)
|
|
|
|
printTemplateParameters(D->getTemplateParameterList(I));
|
|
|
|
}
|
2016-11-10 16:49:37 +08:00
|
|
|
|
2012-12-06 06:19:06 +08:00
|
|
|
CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
|
2014-02-26 02:03:55 +08:00
|
|
|
CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
|
2017-02-18 09:01:48 +08:00
|
|
|
CXXDeductionGuideDecl *GuideDecl = dyn_cast<CXXDeductionGuideDecl>(D);
|
2009-05-30 12:20:30 +08:00
|
|
|
if (!Policy.SuppressSpecifiers) {
|
2013-04-04 03:27:57 +08:00
|
|
|
switch (D->getStorageClass()) {
|
2010-08-26 11:08:43 +08:00
|
|
|
case SC_None: break;
|
|
|
|
case SC_Extern: Out << "extern "; break;
|
|
|
|
case SC_Static: Out << "static "; break;
|
|
|
|
case SC_PrivateExtern: Out << "__private_extern__ "; break;
|
2015-09-30 22:08:20 +08:00
|
|
|
case SC_Auto: case SC_Register:
|
2011-09-20 05:14:35 +08:00
|
|
|
llvm_unreachable("invalid for functions");
|
2009-05-30 12:20:30 +08:00
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
|
2011-09-09 10:06:17 +08:00
|
|
|
if (D->isInlineSpecified()) Out << "inline ";
|
2009-05-30 12:20:30 +08:00
|
|
|
if (D->isVirtualAsWritten()) Out << "virtual ";
|
2011-09-09 10:06:17 +08:00
|
|
|
if (D->isModulePrivate()) Out << "__module_private__ ";
|
2014-02-26 02:49:49 +08:00
|
|
|
if (D->isConstexpr() && !D->isExplicitlyDefaulted()) Out << "constexpr ";
|
2014-02-26 02:03:55 +08:00
|
|
|
if ((CDecl && CDecl->isExplicitSpecified()) ||
|
2017-02-18 09:01:48 +08:00
|
|
|
(ConversionDecl && ConversionDecl->isExplicitSpecified()) ||
|
|
|
|
(GuideDecl && GuideDecl->isExplicitSpecified()))
|
2012-12-06 06:19:06 +08:00
|
|
|
Out << "explicit ";
|
2009-05-30 12:20:30 +08:00
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
|
2009-05-30 13:39:39 +08:00
|
|
|
PrintingPolicy SubPolicy(Policy);
|
|
|
|
SubPolicy.SuppressSpecifiers = false;
|
2017-04-12 00:46:03 +08:00
|
|
|
std::string Proto;
|
2017-11-23 13:38:20 +08:00
|
|
|
|
|
|
|
if (Policy.FullyQualifiedName) {
|
|
|
|
Proto += D->getQualifiedNameAsString();
|
|
|
|
} else {
|
|
|
|
if (!Policy.SuppressScope) {
|
|
|
|
if (const NestedNameSpecifier *NS = D->getQualifier()) {
|
|
|
|
llvm::raw_string_ostream OS(Proto);
|
|
|
|
NS->print(OS, Policy);
|
|
|
|
}
|
2017-04-12 00:46:03 +08:00
|
|
|
}
|
2017-11-23 13:38:20 +08:00
|
|
|
Proto += D->getNameInfo().getAsString();
|
2017-04-12 00:46:03 +08:00
|
|
|
}
|
2017-11-23 13:38:20 +08:00
|
|
|
|
2017-02-18 09:01:48 +08:00
|
|
|
if (GuideDecl)
|
|
|
|
Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString();
|
2016-11-10 16:49:37 +08:00
|
|
|
if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) {
|
|
|
|
llvm::raw_string_ostream POut(Proto);
|
2017-08-17 21:41:55 +08:00
|
|
|
DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation);
|
2016-11-10 16:49:37 +08:00
|
|
|
TArgPrinter.printTemplateArguments(*TArgs);
|
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
|
2010-12-15 06:11:44 +08:00
|
|
|
QualType Ty = D->getType();
|
2011-01-19 14:33:43 +08:00
|
|
|
while (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
|
2010-12-15 06:11:44 +08:00
|
|
|
Proto = '(' + Proto + ')';
|
|
|
|
Ty = PT->getInnerType();
|
|
|
|
}
|
|
|
|
|
2013-12-05 09:23:43 +08:00
|
|
|
if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
|
2014-05-12 13:36:57 +08:00
|
|
|
const FunctionProtoType *FT = nullptr;
|
2009-05-30 08:08:05 +08:00
|
|
|
if (D->hasWrittenPrototype())
|
|
|
|
FT = dyn_cast<FunctionProtoType>(AFT);
|
|
|
|
|
|
|
|
Proto += "(";
|
|
|
|
if (FT) {
|
|
|
|
llvm::raw_string_ostream POut(Proto);
|
2017-08-17 21:41:55 +08:00
|
|
|
DeclPrinter ParamPrinter(POut, SubPolicy, Context, Indentation);
|
2009-05-30 08:08:05 +08:00
|
|
|
for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
|
|
|
|
if (i) POut << ", ";
|
|
|
|
ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (FT->isVariadic()) {
|
|
|
|
if (D->getNumParams()) POut << ", ";
|
|
|
|
POut << "...";
|
|
|
|
}
|
2011-05-07 04:44:56 +08:00
|
|
|
} else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) {
|
2009-05-30 12:20:30 +08:00
|
|
|
for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
|
|
|
|
if (i)
|
|
|
|
Proto += ", ";
|
|
|
|
Proto += D->getParamDecl(i)->getNameAsString();
|
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Proto += ")";
|
2009-12-09 01:45:32 +08:00
|
|
|
|
2012-08-10 08:55:35 +08:00
|
|
|
if (FT) {
|
|
|
|
if (FT->isConst())
|
2010-11-20 02:44:34 +08:00
|
|
|
Proto += " const";
|
2012-08-10 08:55:35 +08:00
|
|
|
if (FT->isVolatile())
|
2010-11-20 02:44:34 +08:00
|
|
|
Proto += " volatile";
|
2012-08-10 08:55:35 +08:00
|
|
|
if (FT->isRestrict())
|
2010-11-20 02:44:34 +08:00
|
|
|
Proto += " restrict";
|
2014-02-26 02:49:49 +08:00
|
|
|
|
|
|
|
switch (FT->getRefQualifier()) {
|
|
|
|
case RQ_None:
|
|
|
|
break;
|
|
|
|
case RQ_LValue:
|
|
|
|
Proto += " &";
|
|
|
|
break;
|
|
|
|
case RQ_RValue:
|
|
|
|
Proto += " &&";
|
|
|
|
break;
|
|
|
|
}
|
2010-11-20 02:44:34 +08:00
|
|
|
}
|
2011-03-12 19:50:43 +08:00
|
|
|
|
|
|
|
if (FT && FT->hasDynamicExceptionSpec()) {
|
2009-12-09 01:45:32 +08:00
|
|
|
Proto += " throw(";
|
2011-03-12 19:50:43 +08:00
|
|
|
if (FT->getExceptionSpecType() == EST_MSAny)
|
2009-12-09 01:45:32 +08:00
|
|
|
Proto += "...";
|
|
|
|
else
|
|
|
|
for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) {
|
|
|
|
if (I)
|
|
|
|
Proto += ", ";
|
2011-03-12 19:50:43 +08:00
|
|
|
|
2012-09-11 05:20:09 +08:00
|
|
|
Proto += FT->getExceptionType(I).getAsString(SubPolicy);
|
2009-12-09 01:45:32 +08:00
|
|
|
}
|
|
|
|
Proto += ")";
|
2011-03-12 19:50:43 +08:00
|
|
|
} else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) {
|
|
|
|
Proto += " noexcept";
|
2018-05-03 11:58:32 +08:00
|
|
|
if (isComputedNoexcept(FT->getExceptionSpecType())) {
|
2011-03-12 19:50:43 +08:00
|
|
|
Proto += "(";
|
|
|
|
llvm::raw_string_ostream EOut(Proto);
|
2014-05-12 13:36:57 +08:00
|
|
|
FT->getNoexceptExpr()->printPretty(EOut, nullptr, SubPolicy,
|
2011-03-12 19:50:43 +08:00
|
|
|
Indentation);
|
|
|
|
EOut.flush();
|
|
|
|
Proto += EOut.str();
|
|
|
|
Proto += ")";
|
|
|
|
}
|
2009-12-09 01:45:32 +08:00
|
|
|
}
|
|
|
|
|
2012-12-06 06:19:06 +08:00
|
|
|
if (CDecl) {
|
2017-11-16 09:31:27 +08:00
|
|
|
if (!Policy.TerseOutput)
|
|
|
|
PrintConstructorInitializers(CDecl, Proto);
|
2014-02-26 02:49:49 +08:00
|
|
|
} else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) {
|
2013-02-22 13:54:51 +08:00
|
|
|
if (FT && FT->hasTrailingReturn()) {
|
2017-02-18 09:01:48 +08:00
|
|
|
if (!GuideDecl)
|
|
|
|
Out << "auto ";
|
|
|
|
Out << Proto << " -> ";
|
2013-02-22 13:54:51 +08:00
|
|
|
Proto.clear();
|
|
|
|
}
|
2014-01-26 00:55:45 +08:00
|
|
|
AFT->getReturnType().print(Out, Policy, Proto);
|
2014-02-26 02:03:55 +08:00
|
|
|
Proto.clear();
|
2013-02-22 13:54:51 +08:00
|
|
|
}
|
2014-02-26 02:03:55 +08:00
|
|
|
Out << Proto;
|
2009-05-30 08:08:05 +08:00
|
|
|
} else {
|
2012-05-05 12:20:37 +08:00
|
|
|
Ty.print(Out, Policy, Proto);
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
2011-11-20 03:22:57 +08:00
|
|
|
prettyPrintAttributes(D);
|
2009-05-30 08:08:05 +08:00
|
|
|
|
|
|
|
if (D->isPure())
|
|
|
|
Out << " = 0";
|
2011-05-07 04:44:56 +08:00
|
|
|
else if (D->isDeletedAsWritten())
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << " = delete";
|
2012-12-06 06:53:06 +08:00
|
|
|
else if (D->isExplicitlyDefaulted())
|
|
|
|
Out << " = default";
|
2016-11-10 16:49:37 +08:00
|
|
|
else if (D->doesThisDeclarationHaveABody()) {
|
|
|
|
if (!Policy.TerseOutput) {
|
|
|
|
if (!D->hasPrototype() && D->getNumParams()) {
|
|
|
|
// This is a K&R function definition, so we need to print the
|
|
|
|
// parameters.
|
|
|
|
Out << '\n';
|
2017-08-17 21:41:55 +08:00
|
|
|
DeclPrinter ParamPrinter(Out, SubPolicy, Context, Indentation);
|
2016-11-10 16:49:37 +08:00
|
|
|
Indentation += Policy.Indentation;
|
|
|
|
for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
|
|
|
|
Indent();
|
|
|
|
ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
|
|
|
|
Out << ";\n";
|
|
|
|
}
|
|
|
|
Indentation -= Policy.Indentation;
|
|
|
|
} else
|
|
|
|
Out << ' ';
|
2009-05-30 08:08:05 +08:00
|
|
|
|
2016-11-10 16:49:37 +08:00
|
|
|
if (D->getBody())
|
|
|
|
D->getBody()->printPretty(Out, nullptr, SubPolicy, Indentation);
|
|
|
|
} else {
|
2017-11-16 09:28:25 +08:00
|
|
|
if (!Policy.TerseOutput && isa<CXXConstructorDecl>(*D))
|
2016-11-10 16:49:37 +08:00
|
|
|
Out << " {}";
|
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-05 08:38:44 +08:00
|
|
|
void DeclPrinter::VisitFriendDecl(FriendDecl *D) {
|
|
|
|
if (TypeSourceInfo *TSI = D->getFriendType()) {
|
2013-01-31 17:54:08 +08:00
|
|
|
unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists();
|
|
|
|
for (unsigned i = 0; i < NumTPLists; ++i)
|
2016-11-10 16:49:37 +08:00
|
|
|
printTemplateParameters(D->getFriendTypeTemplateParameterList(i));
|
2012-12-22 05:43:05 +08:00
|
|
|
Out << "friend ";
|
|
|
|
Out << " " << TSI->getType().getAsString(Policy);
|
2012-12-05 08:38:44 +08:00
|
|
|
}
|
|
|
|
else if (FunctionDecl *FD =
|
|
|
|
dyn_cast<FunctionDecl>(D->getFriendDecl())) {
|
|
|
|
Out << "friend ";
|
|
|
|
VisitFunctionDecl(FD);
|
|
|
|
}
|
|
|
|
else if (FunctionTemplateDecl *FTD =
|
|
|
|
dyn_cast<FunctionTemplateDecl>(D->getFriendDecl())) {
|
|
|
|
Out << "friend ";
|
|
|
|
VisitFunctionTemplateDecl(FTD);
|
|
|
|
}
|
|
|
|
else if (ClassTemplateDecl *CTD =
|
|
|
|
dyn_cast<ClassTemplateDecl>(D->getFriendDecl())) {
|
|
|
|
Out << "friend ";
|
2012-12-22 05:43:05 +08:00
|
|
|
VisitRedeclarableTemplateDecl(CTD);
|
2012-12-05 08:38:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
|
2015-10-12 14:59:48 +08:00
|
|
|
// FIXME: add printing of pragma attributes if required.
|
2009-05-30 12:20:30 +08:00
|
|
|
if (!Policy.SuppressSpecifiers && D->isMutable())
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << "mutable ";
|
2011-09-09 10:06:17 +08:00
|
|
|
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
|
|
|
|
Out << "__module_private__ ";
|
2009-05-30 08:08:05 +08:00
|
|
|
|
2013-05-02 04:53:21 +08:00
|
|
|
Out << D->getASTContext().getUnqualifiedObjCPointerType(D->getType()).
|
2016-03-19 05:35:59 +08:00
|
|
|
stream(Policy, D->getName(), Indentation);
|
2009-05-30 08:08:05 +08:00
|
|
|
|
|
|
|
if (D->isBitField()) {
|
|
|
|
Out << " : ";
|
2014-05-12 13:36:57 +08:00
|
|
|
D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation);
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
2011-06-12 01:19:42 +08:00
|
|
|
|
|
|
|
Expr *Init = D->getInClassInitializer();
|
|
|
|
if (!Policy.SuppressInitializers && Init) {
|
2012-06-10 11:12:00 +08:00
|
|
|
if (D->getInClassInitStyle() == ICIS_ListInit)
|
|
|
|
Out << " ";
|
|
|
|
else
|
|
|
|
Out << " = ";
|
2014-05-12 13:36:57 +08:00
|
|
|
Init->printPretty(Out, nullptr, Policy, Indentation);
|
2011-06-12 01:19:42 +08:00
|
|
|
}
|
2011-11-20 03:22:57 +08:00
|
|
|
prettyPrintAttributes(D);
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
2011-02-18 04:34:02 +08:00
|
|
|
void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
|
2012-02-07 19:57:57 +08:00
|
|
|
Out << *D << ":";
|
2011-02-18 04:34:02 +08:00
|
|
|
}
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
void DeclPrinter::VisitVarDecl(VarDecl *D) {
|
2015-10-12 14:59:48 +08:00
|
|
|
prettyPrintPragmas(D);
|
2016-07-09 05:09:08 +08:00
|
|
|
|
|
|
|
QualType T = D->getTypeSourceInfo()
|
|
|
|
? D->getTypeSourceInfo()->getType()
|
|
|
|
: D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
|
|
|
|
|
2013-04-13 10:43:54 +08:00
|
|
|
if (!Policy.SuppressSpecifiers) {
|
|
|
|
StorageClass SC = D->getStorageClass();
|
|
|
|
if (SC != SC_None)
|
|
|
|
Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
|
2009-05-30 08:08:05 +08:00
|
|
|
|
2013-05-04 16:27:07 +08:00
|
|
|
switch (D->getTSCSpec()) {
|
|
|
|
case TSCS_unspecified:
|
2013-04-13 10:43:54 +08:00
|
|
|
break;
|
2013-05-04 16:27:07 +08:00
|
|
|
case TSCS___thread:
|
|
|
|
Out << "__thread ";
|
|
|
|
break;
|
|
|
|
case TSCS__Thread_local:
|
2013-04-13 10:43:54 +08:00
|
|
|
Out << "_Thread_local ";
|
|
|
|
break;
|
2013-05-04 16:27:07 +08:00
|
|
|
case TSCS_thread_local:
|
2013-04-13 10:43:54 +08:00
|
|
|
Out << "thread_local ";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (D->isModulePrivate())
|
|
|
|
Out << "__module_private__ ";
|
2016-07-09 05:09:08 +08:00
|
|
|
|
|
|
|
if (D->isConstexpr()) {
|
|
|
|
Out << "constexpr ";
|
|
|
|
T.removeLocalConst();
|
|
|
|
}
|
2013-04-13 10:43:54 +08:00
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
|
2014-07-23 11:17:06 +08:00
|
|
|
printDeclType(T, D->getName());
|
2011-04-15 06:09:26 +08:00
|
|
|
Expr *Init = D->getInit();
|
|
|
|
if (!Policy.SuppressInitializers && Init) {
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
bool ImplicitInit = false;
|
2013-02-04 07:02:47 +08:00
|
|
|
if (CXXConstructExpr *Construct =
|
|
|
|
dyn_cast<CXXConstructExpr>(Init->IgnoreImplicit())) {
|
2013-01-28 05:28:24 +08:00
|
|
|
if (D->getInitStyle() == VarDecl::CallInit &&
|
|
|
|
!Construct->isListInitialization()) {
|
|
|
|
ImplicitInit = Construct->getNumArgs() == 0 ||
|
|
|
|
Construct->getArg(0)->isDefaultArgument();
|
|
|
|
}
|
|
|
|
}
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
if (!ImplicitInit) {
|
2012-10-20 04:36:44 +08:00
|
|
|
if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
Out << "(";
|
|
|
|
else if (D->getInitStyle() == VarDecl::CInit) {
|
|
|
|
Out << " = ";
|
|
|
|
}
|
2016-01-25 18:34:06 +08:00
|
|
|
PrintingPolicy SubPolicy(Policy);
|
|
|
|
SubPolicy.SuppressSpecifiers = false;
|
2016-03-19 05:35:59 +08:00
|
|
|
SubPolicy.IncludeTagDefinition = false;
|
2016-01-25 18:34:06 +08:00
|
|
|
Init->printPretty(Out, nullptr, SubPolicy, Indentation);
|
2012-10-20 04:36:44 +08:00
|
|
|
if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
|
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
llvm-svn: 150318
2012-02-12 07:51:47 +08:00
|
|
|
Out << ")";
|
2010-09-18 07:04:38 +08:00
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
2011-11-20 03:22:57 +08:00
|
|
|
prettyPrintAttributes(D);
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
|
|
|
|
VisitVarDecl(D);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
|
|
|
|
Out << "__asm (";
|
2014-05-12 13:36:57 +08:00
|
|
|
D->getAsmString()->printPretty(Out, nullptr, Policy, Indentation);
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
2011-12-03 07:23:56 +08:00
|
|
|
void DeclPrinter::VisitImportDecl(ImportDecl *D) {
|
2012-12-12 06:11:52 +08:00
|
|
|
Out << "@import " << D->getImportedModule()->getFullModuleName()
|
2011-12-03 07:23:56 +08:00
|
|
|
<< ";\n";
|
|
|
|
}
|
|
|
|
|
2011-03-17 02:37:27 +08:00
|
|
|
void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {
|
|
|
|
Out << "static_assert(";
|
2014-05-12 13:36:57 +08:00
|
|
|
D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation);
|
2015-06-06 02:03:58 +08:00
|
|
|
if (StringLiteral *SL = D->getMessage()) {
|
|
|
|
Out << ", ";
|
|
|
|
SL->printPretty(Out, nullptr, Policy, Indentation);
|
|
|
|
}
|
2011-03-17 02:37:27 +08:00
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// C++ declarations
|
|
|
|
//----------------------------------------------------------------------------
|
2009-05-30 14:58:37 +08:00
|
|
|
void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) {
|
2012-05-01 09:43:38 +08:00
|
|
|
if (D->isInline())
|
|
|
|
Out << "inline ";
|
2011-10-15 02:45:37 +08:00
|
|
|
Out << "namespace " << *D << " {\n";
|
2009-05-30 14:58:37 +08:00
|
|
|
VisitDeclContext(D);
|
|
|
|
Indent() << "}";
|
|
|
|
}
|
|
|
|
|
2009-05-30 14:31:56 +08:00
|
|
|
void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
|
|
|
|
Out << "using namespace ";
|
|
|
|
if (D->getQualifier())
|
|
|
|
D->getQualifier()->print(Out, Policy);
|
2011-10-15 02:45:37 +08:00
|
|
|
Out << *D->getNominatedNamespaceAsWritten();
|
2009-05-30 14:31:56 +08:00
|
|
|
}
|
|
|
|
|
2009-05-30 14:48:27 +08:00
|
|
|
void DeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
|
2011-10-15 02:45:37 +08:00
|
|
|
Out << "namespace " << *D << " = ";
|
2009-05-30 14:48:27 +08:00
|
|
|
if (D->getQualifier())
|
|
|
|
D->getQualifier()->print(Out, Policy);
|
2011-10-15 02:45:37 +08:00
|
|
|
Out << *D->getAliasedNamespace();
|
2009-05-30 14:48:27 +08:00
|
|
|
}
|
|
|
|
|
2013-02-23 01:15:32 +08:00
|
|
|
void DeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
|
|
|
|
prettyPrintAttributes(D);
|
|
|
|
}
|
|
|
|
|
2009-05-30 14:58:37 +08:00
|
|
|
void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
|
2015-10-12 14:59:48 +08:00
|
|
|
// FIXME: add printing of pragma attributes if required.
|
2011-09-09 10:06:17 +08:00
|
|
|
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
|
|
|
|
Out << "__module_private__ ";
|
2009-05-30 14:58:37 +08:00
|
|
|
Out << D->getKindName();
|
2014-09-16 00:45:30 +08:00
|
|
|
|
|
|
|
prettyPrintAttributes(D);
|
|
|
|
|
2016-11-10 16:49:37 +08:00
|
|
|
if (D->getIdentifier()) {
|
2011-10-15 02:45:37 +08:00
|
|
|
Out << ' ' << *D;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2016-11-10 16:49:37 +08:00
|
|
|
if (auto S = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
|
|
|
|
printTemplateArguments(S->getTemplateArgs(), S->getTemplateParameters());
|
|
|
|
else if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(D))
|
|
|
|
printTemplateArguments(S->getTemplateArgs());
|
|
|
|
}
|
|
|
|
|
2011-10-07 14:10:15 +08:00
|
|
|
if (D->isCompleteDefinition()) {
|
2009-05-30 14:58:37 +08:00
|
|
|
// Print the base classes
|
|
|
|
if (D->getNumBases()) {
|
|
|
|
Out << " : ";
|
2009-09-09 23:08:12 +08:00
|
|
|
for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(),
|
|
|
|
BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) {
|
2009-05-30 14:58:37 +08:00
|
|
|
if (Base != D->bases_begin())
|
|
|
|
Out << ", ";
|
|
|
|
|
|
|
|
if (Base->isVirtual())
|
|
|
|
Out << "virtual ";
|
|
|
|
|
2009-08-30 04:36:12 +08:00
|
|
|
AccessSpecifier AS = Base->getAccessSpecifierAsWritten();
|
2014-07-23 11:22:10 +08:00
|
|
|
if (AS != AS_none) {
|
2009-08-30 04:36:12 +08:00
|
|
|
Print(AS);
|
2014-07-23 11:22:10 +08:00
|
|
|
Out << " ";
|
|
|
|
}
|
|
|
|
Out << Base->getType().getAsString(Policy);
|
2011-04-28 01:07:55 +08:00
|
|
|
|
|
|
|
if (Base->isPackExpansion())
|
|
|
|
Out << "...";
|
2009-05-30 14:58:37 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print the class definition
|
2009-05-31 15:13:39 +08:00
|
|
|
// FIXME: Doesn't print access specifiers, e.g., "public:"
|
2016-11-10 16:49:37 +08:00
|
|
|
if (Policy.TerseOutput) {
|
|
|
|
Out << " {}";
|
|
|
|
} else {
|
|
|
|
Out << " {\n";
|
|
|
|
VisitDeclContext(D);
|
|
|
|
Indent() << "}";
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
|
|
|
|
const char *l;
|
|
|
|
if (D->getLanguage() == LinkageSpecDecl::lang_c)
|
|
|
|
l = "C";
|
|
|
|
else {
|
|
|
|
assert(D->getLanguage() == LinkageSpecDecl::lang_cxx &&
|
|
|
|
"unknown language in linkage specification");
|
|
|
|
l = "C++";
|
|
|
|
}
|
|
|
|
|
|
|
|
Out << "extern \"" << l << "\" ";
|
|
|
|
if (D->hasBraces()) {
|
|
|
|
Out << "{\n";
|
|
|
|
VisitDeclContext(D);
|
|
|
|
Indent() << "}";
|
|
|
|
} else
|
2009-06-30 10:36:12 +08:00
|
|
|
Visit(*D->decls_begin());
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 16:49:37 +08:00
|
|
|
void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params) {
|
2011-07-28 08:19:05 +08:00
|
|
|
assert(Params);
|
|
|
|
|
2009-06-04 13:37:43 +08:00
|
|
|
Out << "template <";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-04 13:37:43 +08:00
|
|
|
for (unsigned i = 0, e = Params->size(); i != e; ++i) {
|
|
|
|
if (i != 0)
|
|
|
|
Out << ", ";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-04 13:37:43 +08:00
|
|
|
const Decl *Param = Params->getParam(i);
|
2016-11-10 16:49:37 +08:00
|
|
|
if (auto TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-04 13:37:43 +08:00
|
|
|
if (TTP->wasDeclaredWithTypename())
|
|
|
|
Out << "typename ";
|
|
|
|
else
|
|
|
|
Out << "class ";
|
|
|
|
|
2009-06-13 06:23:22 +08:00
|
|
|
if (TTP->isParameterPack())
|
2014-07-23 11:17:06 +08:00
|
|
|
Out << "...";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-02-07 19:57:57 +08:00
|
|
|
Out << *TTP;
|
2009-06-04 13:37:43 +08:00
|
|
|
|
2016-11-10 16:49:37 +08:00
|
|
|
if (TTP->hasDefaultArgument()) {
|
2009-06-04 13:37:43 +08:00
|
|
|
Out << " = ";
|
|
|
|
Out << TTP->getDefaultArgument().getAsString(Policy);
|
|
|
|
};
|
2016-11-10 16:49:37 +08:00
|
|
|
} else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
|
2014-07-23 11:17:06 +08:00
|
|
|
StringRef Name;
|
|
|
|
if (IdentifierInfo *II = NTTP->getIdentifier())
|
|
|
|
Name = II->getName();
|
|
|
|
printDeclType(NTTP->getType(), Name, NTTP->isParameterPack());
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2016-11-10 16:49:37 +08:00
|
|
|
if (NTTP->hasDefaultArgument()) {
|
2009-06-04 13:37:43 +08:00
|
|
|
Out << " = ";
|
2014-05-12 13:36:57 +08:00
|
|
|
NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy,
|
|
|
|
Indentation);
|
2009-06-04 13:37:43 +08:00
|
|
|
}
|
2016-11-10 16:49:37 +08:00
|
|
|
} else if (auto TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {
|
2011-04-15 21:38:57 +08:00
|
|
|
VisitTemplateDecl(TTPD);
|
|
|
|
// FIXME: print the default argument, if present.
|
2009-06-04 13:37:43 +08:00
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-04 13:37:43 +08:00
|
|
|
Out << "> ";
|
2011-07-28 08:19:05 +08:00
|
|
|
}
|
|
|
|
|
2016-11-10 16:49:37 +08:00
|
|
|
void DeclPrinter::printTemplateArguments(const TemplateArgumentList &Args,
|
|
|
|
const TemplateParameterList *Params) {
|
|
|
|
Out << "<";
|
|
|
|
for (size_t I = 0, E = Args.size(); I < E; ++I) {
|
|
|
|
const TemplateArgument &A = Args[I];
|
|
|
|
if (I)
|
|
|
|
Out << ", ";
|
|
|
|
if (Params) {
|
|
|
|
if (A.getKind() == TemplateArgument::Type)
|
|
|
|
if (auto T = A.getAsType()->getAs<TemplateTypeParmType>()) {
|
|
|
|
auto P = cast<TemplateTypeParmDecl>(Params->getParam(T->getIndex()));
|
|
|
|
Out << *P;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (A.getKind() == TemplateArgument::Template) {
|
|
|
|
if (auto T = A.getAsTemplate().getAsTemplateDecl())
|
|
|
|
if (auto TD = dyn_cast<TemplateTemplateParmDecl>(T)) {
|
|
|
|
auto P = cast<TemplateTemplateParmDecl>(
|
|
|
|
Params->getParam(TD->getIndex()));
|
|
|
|
Out << *P;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (A.getKind() == TemplateArgument::Expression) {
|
|
|
|
if (auto E = dyn_cast<DeclRefExpr>(A.getAsExpr()))
|
|
|
|
if (auto N = dyn_cast<NonTypeTemplateParmDecl>(E->getDecl())) {
|
|
|
|
auto P = cast<NonTypeTemplateParmDecl>(
|
|
|
|
Params->getParam(N->getIndex()));
|
|
|
|
Out << *P;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
A.print(Policy, Out);
|
|
|
|
}
|
|
|
|
Out << ">";
|
|
|
|
}
|
|
|
|
|
2011-07-28 08:19:05 +08:00
|
|
|
void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
|
2016-11-10 16:49:37 +08:00
|
|
|
printTemplateParameters(D->getTemplateParameters());
|
2009-06-04 13:37:43 +08:00
|
|
|
|
2011-04-15 21:38:57 +08:00
|
|
|
if (const TemplateTemplateParmDecl *TTP =
|
|
|
|
dyn_cast<TemplateTemplateParmDecl>(D)) {
|
2011-01-05 23:48:55 +08:00
|
|
|
Out << "class ";
|
|
|
|
if (TTP->isParameterPack())
|
|
|
|
Out << "...";
|
|
|
|
Out << D->getName();
|
2010-07-10 04:25:10 +08:00
|
|
|
} else {
|
|
|
|
Visit(D->getTemplatedDecl());
|
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
2011-07-28 08:19:05 +08:00
|
|
|
void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
2016-11-10 16:49:37 +08:00
|
|
|
prettyPrintPragmas(D->getTemplatedDecl());
|
2017-04-18 23:12:34 +08:00
|
|
|
// Print any leading template parameter lists.
|
|
|
|
if (const FunctionDecl *FD = D->getTemplatedDecl()) {
|
|
|
|
for (unsigned I = 0, NumTemplateParams = FD->getNumTemplateParameterLists();
|
|
|
|
I < NumTemplateParams; ++I)
|
|
|
|
printTemplateParameters(FD->getTemplateParameterList(I));
|
|
|
|
}
|
2016-11-10 16:49:37 +08:00
|
|
|
VisitRedeclarableTemplateDecl(D);
|
|
|
|
|
2017-02-18 09:01:48 +08:00
|
|
|
// Never print "instantiations" for deduction guides (they don't really
|
|
|
|
// have them).
|
|
|
|
if (PrintInstantiation &&
|
|
|
|
!isa<CXXDeductionGuideDecl>(D->getTemplatedDecl())) {
|
2016-11-10 16:49:37 +08:00
|
|
|
FunctionDecl *PrevDecl = D->getTemplatedDecl();
|
|
|
|
const FunctionDecl *Def;
|
|
|
|
if (PrevDecl->isDefined(Def) && Def != PrevDecl)
|
|
|
|
return;
|
|
|
|
for (auto *I : D->specializations())
|
|
|
|
if (I->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) {
|
|
|
|
if (!PrevDecl->isThisDeclarationADefinition())
|
|
|
|
Out << ";\n";
|
|
|
|
Indent();
|
|
|
|
prettyPrintPragmas(I);
|
|
|
|
Visit(I);
|
|
|
|
}
|
2011-07-28 08:19:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
2016-11-10 16:49:37 +08:00
|
|
|
VisitRedeclarableTemplateDecl(D);
|
|
|
|
|
2011-07-28 08:19:05 +08:00
|
|
|
if (PrintInstantiation) {
|
2016-11-10 16:49:37 +08:00
|
|
|
for (auto *I : D->specializations())
|
|
|
|
if (I->getSpecializationKind() == TSK_ImplicitInstantiation) {
|
|
|
|
if (D->isThisDeclarationADefinition())
|
|
|
|
Out << ";";
|
|
|
|
Out << "\n";
|
|
|
|
Visit(I);
|
|
|
|
}
|
2011-07-28 08:19:05 +08:00
|
|
|
}
|
2016-11-10 16:49:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitClassTemplateSpecializationDecl(
|
|
|
|
ClassTemplateSpecializationDecl *D) {
|
|
|
|
Out << "template<> ";
|
|
|
|
VisitCXXRecordDecl(D);
|
|
|
|
}
|
2011-07-28 08:19:05 +08:00
|
|
|
|
2016-11-10 16:49:37 +08:00
|
|
|
void DeclPrinter::VisitClassTemplatePartialSpecializationDecl(
|
|
|
|
ClassTemplatePartialSpecializationDecl *D) {
|
|
|
|
printTemplateParameters(D->getTemplateParameters());
|
|
|
|
VisitCXXRecordDecl(D);
|
2011-07-28 08:19:05 +08:00
|
|
|
}
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// Objective-C declarations
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
2015-06-20 02:14:38 +08:00
|
|
|
void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,
|
|
|
|
Decl::ObjCDeclQualifier Quals,
|
|
|
|
QualType T) {
|
|
|
|
Out << '(';
|
|
|
|
if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_In)
|
|
|
|
Out << "in ";
|
|
|
|
if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Inout)
|
|
|
|
Out << "inout ";
|
|
|
|
if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Out)
|
|
|
|
Out << "out ";
|
|
|
|
if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Bycopy)
|
|
|
|
Out << "bycopy ";
|
|
|
|
if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Byref)
|
|
|
|
Out << "byref ";
|
|
|
|
if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Oneway)
|
|
|
|
Out << "oneway ";
|
|
|
|
if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_CSNullability) {
|
2015-06-25 06:02:08 +08:00
|
|
|
if (auto nullability = AttributedType::stripOuterNullability(T))
|
|
|
|
Out << getNullabilitySpelling(*nullability, true) << ' ';
|
2015-06-20 02:14:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Out << Ctx.getUnqualifiedObjCPointerType(T).getAsString(Policy);
|
|
|
|
Out << ')';
|
|
|
|
}
|
|
|
|
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
void DeclPrinter::PrintObjCTypeParams(ObjCTypeParamList *Params) {
|
|
|
|
Out << "<";
|
|
|
|
unsigned First = true;
|
|
|
|
for (auto *Param : *Params) {
|
|
|
|
if (First) {
|
|
|
|
First = false;
|
|
|
|
} else {
|
|
|
|
Out << ", ";
|
|
|
|
}
|
|
|
|
|
2015-07-07 11:58:54 +08:00
|
|
|
switch (Param->getVariance()) {
|
|
|
|
case ObjCTypeParamVariance::Invariant:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjCTypeParamVariance::Covariant:
|
|
|
|
Out << "__covariant ";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjCTypeParamVariance::Contravariant:
|
|
|
|
Out << "__contravariant ";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
Out << Param->getDeclName().getAsString();
|
|
|
|
|
|
|
|
if (Param->hasExplicitBound()) {
|
|
|
|
Out << " : " << Param->getUnderlyingType().getAsString(Policy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Out << ">";
|
|
|
|
}
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
void DeclPrinter::VisitObjCMethodDecl(ObjCMethodDecl *OMD) {
|
|
|
|
if (OMD->isInstanceMethod())
|
2009-05-30 08:56:08 +08:00
|
|
|
Out << "- ";
|
2009-09-09 23:08:12 +08:00
|
|
|
else
|
2009-05-30 08:56:08 +08:00
|
|
|
Out << "+ ";
|
2015-06-20 02:14:38 +08:00
|
|
|
if (!OMD->getReturnType().isNull()) {
|
|
|
|
PrintObjCMethodType(OMD->getASTContext(), OMD->getObjCDeclQualifier(),
|
|
|
|
OMD->getReturnType());
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
std::string name = OMD->getSelector().getAsString();
|
|
|
|
std::string::size_type pos, lastPos = 0;
|
2016-06-24 12:05:48 +08:00
|
|
|
for (const auto *PI : OMD->parameters()) {
|
2009-09-09 23:08:12 +08:00
|
|
|
// FIXME: selector is missing here!
|
2011-10-15 02:45:37 +08:00
|
|
|
pos = name.find_first_of(':', lastPos);
|
2017-06-02 23:02:59 +08:00
|
|
|
if (lastPos != 0)
|
|
|
|
Out << " ";
|
|
|
|
Out << name.substr(lastPos, pos - lastPos) << ':';
|
2015-06-20 02:14:38 +08:00
|
|
|
PrintObjCMethodType(OMD->getASTContext(),
|
|
|
|
PI->getObjCDeclQualifier(),
|
|
|
|
PI->getType());
|
|
|
|
Out << *PI;
|
2009-05-30 08:08:05 +08:00
|
|
|
lastPos = pos + 1;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (OMD->param_begin() == OMD->param_end())
|
2017-06-02 23:02:59 +08:00
|
|
|
Out << name;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (OMD->isVariadic())
|
|
|
|
Out << ", ...";
|
2014-10-04 04:05:33 +08:00
|
|
|
|
|
|
|
prettyPrintAttributes(OMD);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-10-18 05:58:03 +08:00
|
|
|
if (OMD->getBody() && !Policy.TerseOutput) {
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << ' ';
|
2014-05-12 13:36:57 +08:00
|
|
|
OMD->getBody()->printPretty(Out, nullptr, Policy);
|
2009-05-30 08:56:08 +08:00
|
|
|
}
|
2012-12-20 07:36:00 +08:00
|
|
|
else if (Policy.PolishForDeclaration)
|
2012-12-19 07:02:59 +08:00
|
|
|
Out << ';';
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
|
|
|
|
std::string I = OID->getNameAsString();
|
|
|
|
ObjCInterfaceDecl *SID = OID->getSuperClass();
|
|
|
|
|
2014-10-04 04:05:33 +08:00
|
|
|
bool eolnOut = false;
|
2009-05-30 08:08:05 +08:00
|
|
|
if (SID)
|
2011-10-15 02:45:37 +08:00
|
|
|
Out << "@implementation " << I << " : " << *SID;
|
2009-05-30 08:08:05 +08:00
|
|
|
else
|
|
|
|
Out << "@implementation " << I;
|
2012-12-04 08:47:33 +08:00
|
|
|
|
|
|
|
if (OID->ivar_size() > 0) {
|
|
|
|
Out << "{\n";
|
2014-10-04 04:05:33 +08:00
|
|
|
eolnOut = true;
|
2012-12-04 08:47:33 +08:00
|
|
|
Indentation += Policy.Indentation;
|
2014-03-14 23:16:45 +08:00
|
|
|
for (const auto *I : OID->ivars()) {
|
2013-05-02 04:53:21 +08:00
|
|
|
Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).
|
2014-03-14 23:16:45 +08:00
|
|
|
getAsString(Policy) << ' ' << *I << ";\n";
|
2012-12-04 08:47:33 +08:00
|
|
|
}
|
|
|
|
Indentation -= Policy.Indentation;
|
|
|
|
Out << "}\n";
|
|
|
|
}
|
2014-10-04 04:05:33 +08:00
|
|
|
else if (SID || (OID->decls_begin() != OID->decls_end())) {
|
|
|
|
Out << "\n";
|
|
|
|
eolnOut = true;
|
|
|
|
}
|
2009-05-30 08:56:08 +08:00
|
|
|
VisitDeclContext(OID, false);
|
2014-10-04 04:05:33 +08:00
|
|
|
if (!eolnOut)
|
|
|
|
Out << "\n";
|
2009-05-30 08:56:08 +08:00
|
|
|
Out << "@end";
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
|
|
|
|
std::string I = OID->getNameAsString();
|
|
|
|
ObjCInterfaceDecl *SID = OID->getSuperClass();
|
|
|
|
|
2011-12-16 04:29:51 +08:00
|
|
|
if (!OID->isThisDeclarationADefinition()) {
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
Out << "@class " << I;
|
|
|
|
|
|
|
|
if (auto TypeParams = OID->getTypeParamListAsWritten()) {
|
|
|
|
PrintObjCTypeParams(TypeParams);
|
|
|
|
}
|
|
|
|
|
|
|
|
Out << ";";
|
2011-12-16 04:29:51 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-12-20 07:36:00 +08:00
|
|
|
bool eolnOut = false;
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
Out << "@interface " << I;
|
|
|
|
|
|
|
|
if (auto TypeParams = OID->getTypeParamListAsWritten()) {
|
|
|
|
PrintObjCTypeParams(TypeParams);
|
|
|
|
}
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (SID)
|
2015-10-01 08:53:13 +08:00
|
|
|
Out << " : " << QualType(OID->getSuperClassType(), 0).getAsString(Policy);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
// Protocols?
|
|
|
|
const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
|
|
|
|
if (!Protocols.empty()) {
|
|
|
|
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
|
|
|
|
E = Protocols.end(); I != E; ++I)
|
2011-10-15 02:45:37 +08:00
|
|
|
Out << (I == Protocols.begin() ? '<' : ',') << **I;
|
2009-05-30 08:56:08 +08:00
|
|
|
Out << "> ";
|
2012-12-20 07:36:00 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (OID->ivar_size() > 0) {
|
2009-05-30 08:56:08 +08:00
|
|
|
Out << "{\n";
|
2012-12-20 07:36:00 +08:00
|
|
|
eolnOut = true;
|
2009-05-30 08:56:08 +08:00
|
|
|
Indentation += Policy.Indentation;
|
2014-03-14 05:09:43 +08:00
|
|
|
for (const auto *I : OID->ivars()) {
|
|
|
|
Indent() << I->getASTContext()
|
|
|
|
.getUnqualifiedObjCPointerType(I->getType())
|
|
|
|
.getAsString(Policy) << ' ' << *I << ";\n";
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
2009-05-30 08:56:08 +08:00
|
|
|
Indentation -= Policy.Indentation;
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << "}\n";
|
|
|
|
}
|
2014-10-04 04:05:33 +08:00
|
|
|
else if (SID || (OID->decls_begin() != OID->decls_end())) {
|
2012-12-20 07:36:00 +08:00
|
|
|
Out << "\n";
|
|
|
|
eolnOut = true;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
VisitDeclContext(OID, false);
|
2012-12-20 07:36:00 +08:00
|
|
|
if (!eolnOut)
|
2014-10-04 04:05:33 +08:00
|
|
|
Out << "\n";
|
2009-05-30 08:56:08 +08:00
|
|
|
Out << "@end";
|
2009-05-30 08:08:05 +08:00
|
|
|
// FIXME: implement the rest...
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
|
2012-01-02 05:23:57 +08:00
|
|
|
if (!PID->isThisDeclarationADefinition()) {
|
2012-12-20 07:36:00 +08:00
|
|
|
Out << "@protocol " << *PID << ";\n";
|
2012-01-02 05:23:57 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-12-20 07:36:00 +08:00
|
|
|
// Protocols?
|
|
|
|
const ObjCList<ObjCProtocolDecl> &Protocols = PID->getReferencedProtocols();
|
|
|
|
if (!Protocols.empty()) {
|
|
|
|
Out << "@protocol " << *PID;
|
|
|
|
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
|
|
|
|
E = Protocols.end(); I != E; ++I)
|
|
|
|
Out << (I == Protocols.begin() ? '<' : ',') << **I;
|
|
|
|
Out << ">\n";
|
|
|
|
} else
|
|
|
|
Out << "@protocol " << *PID << '\n';
|
2009-05-30 08:56:08 +08:00
|
|
|
VisitDeclContext(PID, false);
|
|
|
|
Out << "@end";
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
|
2011-10-15 02:45:37 +08:00
|
|
|
Out << "@implementation " << *PID->getClassInterface() << '(' << *PID <<")\n";
|
2009-05-30 08:08:05 +08:00
|
|
|
|
|
|
|
VisitDeclContext(PID, false);
|
2009-05-30 08:56:08 +08:00
|
|
|
Out << "@end";
|
2009-05-30 08:08:05 +08:00
|
|
|
// FIXME: implement the rest...
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
Out << "@interface " << *PID->getClassInterface();
|
|
|
|
if (auto TypeParams = PID->getTypeParamList()) {
|
|
|
|
PrintObjCTypeParams(TypeParams);
|
|
|
|
}
|
|
|
|
Out << "(" << *PID << ")\n";
|
2012-12-05 01:20:57 +08:00
|
|
|
if (PID->ivar_size() > 0) {
|
|
|
|
Out << "{\n";
|
|
|
|
Indentation += Policy.Indentation;
|
2014-03-14 21:13:27 +08:00
|
|
|
for (const auto *I : PID->ivars())
|
2013-05-02 04:53:21 +08:00
|
|
|
Indent() << I->getASTContext().getUnqualifiedObjCPointerType(I->getType()).
|
2014-03-14 21:13:27 +08:00
|
|
|
getAsString(Policy) << ' ' << *I << ";\n";
|
2012-12-05 01:20:57 +08:00
|
|
|
Indentation -= Policy.Indentation;
|
|
|
|
Out << "}\n";
|
|
|
|
}
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
VisitDeclContext(PID, false);
|
2009-05-30 08:56:08 +08:00
|
|
|
Out << "@end";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
// FIXME: implement the rest...
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
|
2011-10-15 02:45:37 +08:00
|
|
|
Out << "@compatibility_alias " << *AID
|
|
|
|
<< ' ' << *AID->getClassInterface() << ";\n";
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// PrintObjCPropertyDecl - print a property declaration.
|
|
|
|
///
|
|
|
|
void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
|
|
|
|
if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required)
|
|
|
|
Out << "@required\n";
|
|
|
|
else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
|
|
|
|
Out << "@optional\n";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2015-06-20 02:14:38 +08:00
|
|
|
QualType T = PDecl->getType();
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << "@property";
|
|
|
|
if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
|
|
|
|
bool first = true;
|
|
|
|
Out << " (";
|
2009-09-09 23:08:12 +08:00
|
|
|
if (PDecl->getPropertyAttributes() &
|
2009-05-30 08:08:05 +08:00
|
|
|
ObjCPropertyDecl::OBJC_PR_readonly) {
|
|
|
|
Out << (first ? ' ' : ',') << "readonly";
|
|
|
|
first = false;
|
2011-08-18 05:09:35 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-08-18 05:09:35 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
|
2014-01-04 01:59:55 +08:00
|
|
|
Out << (first ? ' ' : ',') << "getter = ";
|
|
|
|
PDecl->getGetterName().print(Out);
|
2011-08-18 05:09:35 +08:00
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
|
2014-01-04 01:59:55 +08:00
|
|
|
Out << (first ? ' ' : ',') << "setter = ";
|
|
|
|
PDecl->getSetterName().print(Out);
|
2011-08-18 05:09:35 +08:00
|
|
|
first = false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-08-18 05:09:35 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
|
|
|
|
Out << (first ? ' ' : ',') << "assign";
|
|
|
|
first = false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-08-18 05:09:35 +08:00
|
|
|
if (PDecl->getPropertyAttributes() &
|
|
|
|
ObjCPropertyDecl::OBJC_PR_readwrite) {
|
|
|
|
Out << (first ? ' ' : ',') << "readwrite";
|
|
|
|
first = false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-08-18 05:09:35 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
|
|
|
|
Out << (first ? ' ' : ',') << "retain";
|
|
|
|
first = false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-08-18 05:09:35 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) {
|
|
|
|
Out << (first ? ' ' : ',') << "strong";
|
|
|
|
first = false;
|
|
|
|
}
|
2011-06-16 07:02:42 +08:00
|
|
|
|
2011-08-18 05:09:35 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
|
|
|
|
Out << (first ? ' ' : ',') << "copy";
|
|
|
|
first = false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-08-18 05:09:35 +08:00
|
|
|
if (PDecl->getPropertyAttributes() &
|
|
|
|
ObjCPropertyDecl::OBJC_PR_nonatomic) {
|
|
|
|
Out << (first ? ' ' : ',') << "nonatomic";
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
if (PDecl->getPropertyAttributes() &
|
|
|
|
ObjCPropertyDecl::OBJC_PR_atomic) {
|
|
|
|
Out << (first ? ' ' : ',') << "atomic";
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
|
2015-06-20 02:14:38 +08:00
|
|
|
if (PDecl->getPropertyAttributes() &
|
|
|
|
ObjCPropertyDecl::OBJC_PR_nullability) {
|
2015-06-20 02:27:52 +08:00
|
|
|
if (auto nullability = AttributedType::stripOuterNullability(T)) {
|
2015-06-20 02:14:46 +08:00
|
|
|
if (*nullability == NullabilityKind::Unspecified &&
|
|
|
|
(PDecl->getPropertyAttributes() &
|
|
|
|
ObjCPropertyDecl::OBJC_PR_null_resettable)) {
|
|
|
|
Out << (first ? ' ' : ',') << "null_resettable";
|
|
|
|
} else {
|
|
|
|
Out << (first ? ' ' : ',')
|
2015-06-25 06:02:08 +08:00
|
|
|
<< getNullabilitySpelling(*nullability, true);
|
2015-06-20 02:14:46 +08:00
|
|
|
}
|
2015-06-20 02:14:38 +08:00
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-27 02:52:43 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_class) {
|
|
|
|
Out << (first ? ' ' : ',') << "class";
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
|
2011-08-18 05:09:35 +08:00
|
|
|
(void) first; // Silence dead store warning due to idiomatic code.
|
|
|
|
Out << " )";
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
2015-06-20 02:14:38 +08:00
|
|
|
Out << ' ' << PDecl->getASTContext().getUnqualifiedObjCPointerType(T).
|
2013-05-02 01:28:37 +08:00
|
|
|
getAsString(Policy) << ' ' << *PDecl;
|
2012-12-20 07:36:00 +08:00
|
|
|
if (Policy.PolishForDeclaration)
|
|
|
|
Out << ';';
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
|
|
|
|
if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
|
2009-05-30 08:56:08 +08:00
|
|
|
Out << "@synthesize ";
|
2009-05-30 08:08:05 +08:00
|
|
|
else
|
2009-05-30 08:56:08 +08:00
|
|
|
Out << "@dynamic ";
|
2011-10-15 02:45:37 +08:00
|
|
|
Out << *PID->getPropertyDecl();
|
2009-05-30 08:08:05 +08:00
|
|
|
if (PID->getPropertyIvarDecl())
|
2011-10-15 02:45:37 +08:00
|
|
|
Out << '=' << *PID->getPropertyIvarDecl();
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
2009-08-29 03:16:39 +08:00
|
|
|
|
|
|
|
void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
|
2013-07-18 01:28:56 +08:00
|
|
|
if (!D->isAccessDeclaration())
|
|
|
|
Out << "using ";
|
2013-07-22 18:54:09 +08:00
|
|
|
if (D->hasTypename())
|
2013-07-18 01:28:56 +08:00
|
|
|
Out << "typename ";
|
2011-02-25 08:36:19 +08:00
|
|
|
D->getQualifier()->print(Out, Policy);
|
2016-10-03 20:22:17 +08:00
|
|
|
|
|
|
|
// Use the correct record name when the using declaration is used for
|
|
|
|
// inheriting constructors.
|
|
|
|
for (const auto *Shadow : D->shadows()) {
|
|
|
|
if (const auto *ConstructorShadow =
|
|
|
|
dyn_cast<ConstructorUsingShadowDecl>(Shadow)) {
|
|
|
|
assert(Shadow->getDeclContext() == ConstructorShadow->getDeclContext());
|
|
|
|
Out << *ConstructorShadow->getNominatedBaseClass();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2011-10-15 02:45:37 +08:00
|
|
|
Out << *D;
|
2009-08-29 03:16:39 +08:00
|
|
|
}
|
|
|
|
|
2009-11-18 10:36:19 +08:00
|
|
|
void
|
|
|
|
DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
|
|
|
|
Out << "using typename ";
|
2011-02-25 08:36:19 +08:00
|
|
|
D->getQualifier()->print(Out, Policy);
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << D->getDeclName();
|
2009-11-18 10:36:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
|
2013-07-18 01:28:56 +08:00
|
|
|
if (!D->isAccessDeclaration())
|
|
|
|
Out << "using ";
|
2011-02-25 08:36:19 +08:00
|
|
|
D->getQualifier()->print(Out, Policy);
|
2015-09-23 21:43:16 +08:00
|
|
|
Out << D->getDeclName();
|
2009-08-29 03:16:39 +08:00
|
|
|
}
|
2009-11-17 13:59:44 +08:00
|
|
|
|
|
|
|
void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
|
|
|
|
// ignore
|
|
|
|
}
|
2013-03-22 14:34:35 +08:00
|
|
|
|
|
|
|
void DeclPrinter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
|
|
|
|
Out << "#pragma omp threadprivate";
|
|
|
|
if (!D->varlist_empty()) {
|
|
|
|
for (OMPThreadPrivateDecl::varlist_iterator I = D->varlist_begin(),
|
|
|
|
E = D->varlist_end();
|
2013-05-13 12:18:18 +08:00
|
|
|
I != E; ++I) {
|
2013-09-26 11:24:06 +08:00
|
|
|
Out << (I == D->varlist_begin() ? '(' : ',');
|
2018-03-01 13:43:23 +08:00
|
|
|
NamedDecl *ND = cast<DeclRefExpr>(*I)->getDecl();
|
2013-09-26 11:24:06 +08:00
|
|
|
ND->printQualifiedName(Out);
|
2013-03-22 14:34:35 +08:00
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-03 13:21:39 +08:00
|
|
|
void DeclPrinter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
|
|
|
|
if (!D->isInvalidDecl()) {
|
|
|
|
Out << "#pragma omp declare reduction (";
|
|
|
|
if (D->getDeclName().getNameKind() == DeclarationName::CXXOperatorName) {
|
|
|
|
static const char *const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
|
|
|
|
nullptr,
|
|
|
|
#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
|
|
|
|
Spelling,
|
|
|
|
#include "clang/Basic/OperatorKinds.def"
|
|
|
|
};
|
|
|
|
const char *OpName =
|
|
|
|
OperatorNames[D->getDeclName().getCXXOverloadedOperator()];
|
|
|
|
assert(OpName && "not an overloaded operator");
|
|
|
|
Out << OpName;
|
|
|
|
} else {
|
|
|
|
assert(D->getDeclName().isIdentifier());
|
|
|
|
D->printName(Out);
|
|
|
|
}
|
|
|
|
Out << " : ";
|
|
|
|
D->getType().print(Out, Policy);
|
|
|
|
Out << " : ";
|
|
|
|
D->getCombiner()->printPretty(Out, nullptr, Policy, 0);
|
|
|
|
Out << ")";
|
|
|
|
if (auto *Init = D->getInitializer()) {
|
|
|
|
Out << " initializer(";
|
2017-09-06 22:49:58 +08:00
|
|
|
switch (D->getInitializerKind()) {
|
|
|
|
case OMPDeclareReductionDecl::DirectInit:
|
|
|
|
Out << "omp_priv(";
|
|
|
|
break;
|
|
|
|
case OMPDeclareReductionDecl::CopyInit:
|
|
|
|
Out << "omp_priv = ";
|
|
|
|
break;
|
|
|
|
case OMPDeclareReductionDecl::CallInit:
|
|
|
|
break;
|
|
|
|
}
|
2016-03-03 13:21:39 +08:00
|
|
|
Init->printPretty(Out, nullptr, Policy, 0);
|
2017-09-06 22:49:58 +08:00
|
|
|
if (D->getInitializerKind() == OMPDeclareReductionDecl::DirectInit)
|
|
|
|
Out << ")";
|
2016-03-03 13:21:39 +08:00
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 13:35:55 +08:00
|
|
|
void DeclPrinter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
|
2016-02-08 17:29:13 +08:00
|
|
|
D->getInit()->printPretty(Out, nullptr, Policy, Indentation);
|
|
|
|
}
|
|
|
|
|