2009-05-30 08:08:05 +08:00
|
|
|
//===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2009-05-30 08:08:05 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
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"
|
2019-05-04 18:49:46 +08:00
|
|
|
#include "clang/AST/DeclTemplate.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.
|
2018-07-31 03:24:48 +08:00
|
|
|
void PrintObjCMethodType(ASTContext &Ctx, Decl::ObjCDeclQualifier Quals,
|
2015-06-20 02:14:38 +08:00
|
|
|
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);
|
2021-05-05 23:55:02 +08:00
|
|
|
void VisitUsingEnumDecl(UsingEnumDecl *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);
|
2019-03-08 01:54:44 +08:00
|
|
|
void VisitOMPAllocateDecl(OMPAllocateDecl *D);
|
2018-09-26 12:28:39 +08:00
|
|
|
void VisitOMPRequiresDecl(OMPRequiresDecl *D);
|
2016-03-03 13:21:39 +08:00
|
|
|
void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
|
2019-02-02 04:25:04 +08:00
|
|
|
void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D);
|
2016-02-11 13:35:55 +08:00
|
|
|
void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
|
2020-01-30 21:00:51 +08:00
|
|
|
void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP);
|
|
|
|
void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *NTTP);
|
2011-07-28 08:19:05 +08:00
|
|
|
|
2019-05-04 18:49:46 +08:00
|
|
|
void printTemplateParameters(const TemplateParameterList *Params,
|
|
|
|
bool OmitTemplateKW = false);
|
2021-05-13 01:28:41 +08:00
|
|
|
void printTemplateArguments(llvm::ArrayRef<TemplateArgument> Args,
|
2021-11-15 03:15:05 +08:00
|
|
|
const TemplateParameterList *Params);
|
2021-05-13 01:28:41 +08:00
|
|
|
void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,
|
2021-11-15 03:15:05 +08:00
|
|
|
const TemplateParameterList *Params);
|
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
|
|
|
}
|
|
|
|
|
2019-05-04 18:49:46 +08:00
|
|
|
void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context,
|
|
|
|
bool OmitTemplateKW) const {
|
|
|
|
print(Out, Context, Context.getPrintingPolicy(), OmitTemplateKW);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context,
|
|
|
|
const PrintingPolicy &Policy,
|
|
|
|
bool OmitTemplateKW) const {
|
|
|
|
DeclPrinter Printer(Out, Policy, Context);
|
|
|
|
Printer.printTemplateParameters(this, OmitTemplateKW);
|
|
|
|
}
|
|
|
|
|
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();
|
2021-10-21 01:29:02 +08:00
|
|
|
else if (const ObjCObjectPointerType *OPT =
|
|
|
|
BaseType->getAs<ObjCObjectPointerType>())
|
|
|
|
BaseType = OPT->getPointeeType();
|
2012-10-12 04:58:14 +08:00
|
|
|
else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>())
|
|
|
|
BaseType = BPy->getPointeeType();
|
2021-10-21 01:29:02 +08:00
|
|
|
else if (const ArrayType *ATy = dyn_cast<ArrayType>(BaseType))
|
2009-05-30 12:20:30 +08:00
|
|
|
BaseType = ATy->getElementType();
|
2021-10-21 01:29:02 +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();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-12-10 01:27:46 +08:00
|
|
|
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) {
|
2020-05-28 00:17:07 +08:00
|
|
|
const auto AccessSpelling = getAccessSpelling(AS);
|
|
|
|
if (AccessSpelling.empty())
|
|
|
|
llvm_unreachable("No access specifier!");
|
|
|
|
Out << AccessSpelling;
|
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)
|
2021-02-19 20:14:55 +08:00
|
|
|
SimpleInit->printPretty(Out, nullptr, Policy, Indentation, "\n",
|
|
|
|
&Context);
|
2017-11-16 09:31:27 +08:00
|
|
|
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 << ", ";
|
2021-02-19 20:14:55 +08:00
|
|
|
Args[I]->printPretty(Out, nullptr, Policy, Indentation, "\n",
|
|
|
|
&Context);
|
2017-11-16 09:31:27 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
2018-09-26 12:28:39 +08:00
|
|
|
if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D) ||
|
2019-03-08 01:54:44 +08:00
|
|
|
isa<OMPDeclareMapperDecl>(*D) || isa<OMPRequiresDecl>(*D) ||
|
|
|
|
isa<OMPAllocateDecl>(*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 ";
|
2018-07-31 03:24:48 +08:00
|
|
|
|
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);
|
|
|
|
|
2020-08-05 19:10:16 +08:00
|
|
|
if (D->getDeclName())
|
|
|
|
Out << ' ' << D->getDeclName();
|
2010-12-02 00:01:08 +08:00
|
|
|
|
2020-05-06 02:01:04 +08:00
|
|
|
if (D->isFixed())
|
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 << " = ";
|
2018-09-15 10:02:31 +08:00
|
|
|
Init->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-09 11:59:21 +08:00
|
|
|
static void printExplicitSpecifier(ExplicitSpecifier ES, llvm::raw_ostream &Out,
|
2021-02-19 20:14:55 +08:00
|
|
|
PrintingPolicy &Policy, unsigned Indentation,
|
|
|
|
const ASTContext &Context) {
|
2019-05-09 11:59:21 +08:00
|
|
|
std::string Proto = "explicit";
|
|
|
|
llvm::raw_string_ostream EOut(Proto);
|
|
|
|
if (ES.getExpr()) {
|
|
|
|
EOut << "(";
|
2021-02-19 20:14:55 +08:00
|
|
|
ES.getExpr()->printPretty(EOut, nullptr, Policy, Indentation, "\n",
|
|
|
|
&Context);
|
2019-05-09 11:59:21 +08:00
|
|
|
EOut << ")";
|
|
|
|
}
|
|
|
|
EOut << " ";
|
|
|
|
EOut.flush();
|
2022-01-27 01:24:37 +08:00
|
|
|
Out << Proto;
|
2019-05-09 11:59:21 +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()) {
|
2021-01-05 06:17:45 +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;
|
|
|
|
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__ ";
|
2019-06-14 16:56:20 +08:00
|
|
|
if (D->isConstexprSpecified() && !D->isExplicitlyDefaulted())
|
|
|
|
Out << "constexpr ";
|
|
|
|
if (D->isConsteval()) Out << "consteval ";
|
2019-05-09 11:59:21 +08:00
|
|
|
ExplicitSpecifier ExplicitSpec = ExplicitSpecifier::getFromDecl(D);
|
|
|
|
if (ExplicitSpec.isSpecified())
|
2021-02-19 20:14:55 +08:00
|
|
|
printExplicitSpecifier(ExplicitSpec, Out, Policy, Indentation, Context);
|
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 {
|
2019-11-16 02:19:17 +08:00
|
|
|
llvm::raw_string_ostream OS(Proto);
|
2017-11-23 13:38:20 +08:00
|
|
|
if (!Policy.SuppressScope) {
|
|
|
|
if (const NestedNameSpecifier *NS = D->getQualifier()) {
|
|
|
|
NS->print(OS, Policy);
|
|
|
|
}
|
2017-04-12 00:46:03 +08:00
|
|
|
}
|
2019-11-16 02:19:17 +08:00
|
|
|
D->getNameInfo().printName(OS, Policy);
|
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();
|
2019-11-14 21:16:14 +08:00
|
|
|
if (D->isFunctionTemplateSpecialization()) {
|
2016-11-10 16:49:37 +08:00
|
|
|
llvm::raw_string_ostream POut(Proto);
|
2017-08-17 21:41:55 +08:00
|
|
|
DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation);
|
2019-11-14 21:16:14 +08:00
|
|
|
const auto *TArgAsWritten = D->getTemplateSpecializationArgsAsWritten();
|
|
|
|
if (TArgAsWritten && !Policy.PrintCanonicalTypes)
|
2021-11-15 03:15:05 +08:00
|
|
|
TArgPrinter.printTemplateArguments(TArgAsWritten->arguments(), nullptr);
|
2019-11-14 21:16:14 +08:00
|
|
|
else if (const TemplateArgumentList *TArgs =
|
|
|
|
D->getTemplateSpecializationArgs())
|
2021-11-15 03:15:05 +08:00
|
|
|
TArgPrinter.printTemplateArguments(TArgs->asArray(), nullptr);
|
2016-11-10 16:49:37 +08:00
|
|
|
}
|
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 += ")";
|
2018-07-31 03:24:48 +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 += "...";
|
2018-07-31 03:24:48 +08:00
|
|
|
else
|
2009-12-09 01:45:32 +08:00
|
|
|
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,
|
2021-02-19 20:14:55 +08:00
|
|
|
Indentation, "\n", &Context);
|
2011-03-12 19:50:43 +08:00
|
|
|
EOut.flush();
|
|
|
|
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;
|
2020-01-09 21:07:51 +08:00
|
|
|
|
|
|
|
if (Expr *TrailingRequiresClause = D->getTrailingRequiresClause()) {
|
|
|
|
Out << " requires ";
|
2021-02-19 20:14:55 +08:00
|
|
|
TrailingRequiresClause->printPretty(Out, nullptr, SubPolicy, Indentation,
|
|
|
|
"\n", &Context);
|
2020-01-09 21:07:51 +08:00
|
|
|
}
|
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;
|
2021-11-15 12:44:27 +08:00
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
|
2016-11-10 16:49:37 +08:00
|
|
|
if (D->getBody())
|
2021-11-15 12:44:27 +08:00
|
|
|
D->getBody()->printPrettyControlled(Out, nullptr, SubPolicy, Indentation, "\n",
|
2021-02-19 20:14:55 +08:00
|
|
|
&Context);
|
2016-11-10 16:49:37 +08:00
|
|
|
} 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 << " : ";
|
2021-02-19 20:14:55 +08:00
|
|
|
D->getBitWidth()->printPretty(Out, nullptr, Policy, Indentation, "\n",
|
|
|
|
&Context);
|
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 << " = ";
|
2021-02-19 20:14:55 +08:00
|
|
|
Init->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);
|
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();
|
2021-01-05 06:17:45 +08:00
|
|
|
if (SC != SC_None)
|
2013-04-13 10:43:54 +08:00
|
|
|
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
|
|
|
|
2021-12-30 08:57:47 +08:00
|
|
|
printDeclType(T, (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
|
|
|
|
D->getIdentifier())
|
|
|
|
? D->getIdentifier()->deuglifiedName()
|
|
|
|
: 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;
|
2021-02-19 20:14:55 +08:00
|
|
|
Init->printPretty(Out, nullptr, SubPolicy, Indentation, "\n", &Context);
|
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 (";
|
2021-02-19 20:14:55 +08:00
|
|
|
D->getAsmString()->printPretty(Out, nullptr, Policy, Indentation, "\n",
|
|
|
|
&Context);
|
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(";
|
2021-02-19 20:14:55 +08:00
|
|
|
D->getAssertExpr()->printPretty(Out, nullptr, Policy, Indentation, "\n",
|
|
|
|
&Context);
|
2015-06-06 02:03:58 +08:00
|
|
|
if (StringLiteral *SL = D->getMessage()) {
|
|
|
|
Out << ", ";
|
2021-02-19 20:14:55 +08:00
|
|
|
SL->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);
|
2015-06-06 02:03:58 +08:00
|
|
|
}
|
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 ";
|
2020-08-05 19:10:16 +08:00
|
|
|
|
|
|
|
Out << "namespace ";
|
|
|
|
if (D->getDeclName())
|
|
|
|
Out << D->getDeclName() << ' ';
|
|
|
|
Out << "{\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
|
|
|
|
2019-11-14 21:16:14 +08:00
|
|
|
if (auto S = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
|
|
|
|
ArrayRef<TemplateArgument> Args = S->getTemplateArgs().asArray();
|
|
|
|
if (!Policy.PrintCanonicalTypes)
|
|
|
|
if (const auto* TSI = S->getTypeAsWritten())
|
|
|
|
if (const auto *TST =
|
|
|
|
dyn_cast<TemplateSpecializationType>(TSI->getType()))
|
|
|
|
Args = TST->template_arguments();
|
2021-05-13 01:28:41 +08:00
|
|
|
printTemplateArguments(
|
2021-11-15 03:15:05 +08:00
|
|
|
Args, S->getSpecializedTemplate()->getTemplateParameters());
|
2019-11-14 21:16:14 +08:00
|
|
|
}
|
2016-11-10 16:49:37 +08:00
|
|
|
}
|
|
|
|
|
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;
|
2019-11-07 18:28:48 +08:00
|
|
|
if (D->getLanguage() == LinkageSpecDecl::lang_c)
|
2009-05-30 08:08:05 +08:00
|
|
|
l = "C";
|
2019-11-07 18:28:48 +08:00
|
|
|
else {
|
|
|
|
assert(D->getLanguage() == LinkageSpecDecl::lang_cxx &&
|
|
|
|
"unknown language in linkage specification");
|
2009-05-30 08:08:05 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2019-05-04 18:49:46 +08:00
|
|
|
void DeclPrinter::printTemplateParameters(const TemplateParameterList *Params,
|
|
|
|
bool OmitTemplateKW) {
|
2011-07-28 08:19:05 +08:00
|
|
|
assert(Params);
|
|
|
|
|
2019-05-04 18:49:46 +08:00
|
|
|
if (!OmitTemplateKW)
|
|
|
|
Out << "template ";
|
|
|
|
Out << '<';
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2019-05-04 18:49:46 +08:00
|
|
|
bool NeedComma = false;
|
|
|
|
for (const Decl *Param : *Params) {
|
|
|
|
if (Param->isImplicit())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (NeedComma)
|
2009-06-04 13:37:43 +08:00
|
|
|
Out << ", ";
|
2019-05-04 18:49:46 +08:00
|
|
|
else
|
|
|
|
NeedComma = true;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2020-01-30 21:00:51 +08:00
|
|
|
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
|
|
|
|
VisitTemplateTypeParmDecl(TTP);
|
2016-11-10 16:49:37 +08:00
|
|
|
} else if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
|
2020-01-30 21:00:51 +08:00
|
|
|
VisitNonTypeTemplateParmDecl(NTTP);
|
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
|
|
|
|
2019-05-04 18:49:46 +08:00
|
|
|
Out << '>';
|
|
|
|
if (!OmitTemplateKW)
|
|
|
|
Out << ' ';
|
2011-07-28 08:19:05 +08:00
|
|
|
}
|
|
|
|
|
2021-05-13 01:28:41 +08:00
|
|
|
void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgument> Args,
|
2021-11-15 03:15:05 +08:00
|
|
|
const TemplateParameterList *Params) {
|
2016-11-10 16:49:37 +08:00
|
|
|
Out << "<";
|
|
|
|
for (size_t I = 0, E = Args.size(); I < E; ++I) {
|
|
|
|
if (I)
|
|
|
|
Out << ", ";
|
2021-11-15 03:15:05 +08:00
|
|
|
if (!Params)
|
2021-05-13 01:28:41 +08:00
|
|
|
Args[I].print(Policy, Out, /*IncludeType*/ true);
|
|
|
|
else
|
2021-09-20 11:58:47 +08:00
|
|
|
Args[I].print(Policy, Out,
|
|
|
|
TemplateParameterList::shouldIncludeTypeForArgument(
|
|
|
|
Policy, Params, I));
|
2019-11-14 21:16:14 +08:00
|
|
|
}
|
|
|
|
Out << ">";
|
|
|
|
}
|
|
|
|
|
2021-05-13 01:28:41 +08:00
|
|
|
void DeclPrinter::printTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,
|
2021-11-15 03:15:05 +08:00
|
|
|
const TemplateParameterList *Params) {
|
2019-11-14 21:16:14 +08:00
|
|
|
Out << "<";
|
|
|
|
for (size_t I = 0, E = Args.size(); I < E; ++I) {
|
|
|
|
if (I)
|
|
|
|
Out << ", ";
|
2021-11-15 03:15:05 +08:00
|
|
|
if (!Params)
|
2021-05-13 01:28:41 +08:00
|
|
|
Args[I].getArgument().print(Policy, Out, /*IncludeType*/ true);
|
|
|
|
else
|
|
|
|
Args[I].getArgument().print(
|
|
|
|
Policy, Out,
|
2021-09-20 11:58:47 +08:00
|
|
|
TemplateParameterList::shouldIncludeTypeForArgument(Policy, Params,
|
|
|
|
I));
|
2016-11-10 16:49:37 +08:00
|
|
|
}
|
|
|
|
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)) {
|
2020-08-05 19:10:16 +08:00
|
|
|
Out << "class";
|
|
|
|
|
2011-01-05 23:48:55 +08:00
|
|
|
if (TTP->isParameterPack())
|
2020-08-05 19:10:16 +08:00
|
|
|
Out << " ...";
|
|
|
|
else if (TTP->getDeclName())
|
|
|
|
Out << ' ';
|
|
|
|
|
2021-12-30 08:57:47 +08:00
|
|
|
if (TTP->getDeclName()) {
|
|
|
|
if (Policy.CleanUglifiedParameters && TTP->getIdentifier())
|
|
|
|
Out << TTP->getIdentifier()->deuglifiedName();
|
|
|
|
else
|
|
|
|
Out << TTP->getDeclName();
|
|
|
|
}
|
2019-07-11 05:25:49 +08:00
|
|
|
} else if (auto *TD = D->getTemplatedDecl())
|
|
|
|
Visit(TD);
|
|
|
|
else if (const auto *Concept = dyn_cast<ConceptDecl>(D)) {
|
|
|
|
Out << "concept " << Concept->getName() << " = " ;
|
2021-02-19 20:14:55 +08:00
|
|
|
Concept->getConstraintExpr()->printPretty(Out, nullptr, Policy, Indentation,
|
|
|
|
"\n", &Context);
|
2010-07-10 04:25:10 +08:00
|
|
|
}
|
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);
|
2018-08-15 02:31:20 +08:00
|
|
|
// Declare target attribute is special one, natural spelling for the pragma
|
|
|
|
// assumes "ending" construct so print it here.
|
|
|
|
if (D->getTemplatedDecl()->hasAttr<OMPDeclareTargetDeclAttr>())
|
|
|
|
Out << "#pragma omp end declare target\n";
|
2016-11-10 16:49:37 +08:00
|
|
|
|
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";
|
2021-11-15 10:59:41 +08:00
|
|
|
Indent();
|
2016-11-10 16:49:37 +08:00
|
|
|
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
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,
|
|
|
|
Decl::ObjCDeclQualifier Quals,
|
2015-06-20 02:14:38 +08:00
|
|
|
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
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-08-05 19:10:16 +08:00
|
|
|
Out << Param->getDeclName();
|
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
|
|
|
|
|
|
|
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) << ':';
|
2018-07-31 03:24:48 +08:00
|
|
|
PrintObjCMethodType(OMD->getASTContext(),
|
2015-06-20 02:14:38 +08:00
|
|
|
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 << ", ...";
|
2018-07-31 03:24:48 +08:00
|
|
|
|
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 << ' ';
|
2021-02-19 20:14:55 +08:00
|
|
|
OMD->getBody()->printPretty(Out, nullptr, Policy, Indentation, "\n",
|
|
|
|
&Context);
|
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;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
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);
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
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) {
|
2020-07-10 05:32:05 +08:00
|
|
|
Out << "@implementation ";
|
|
|
|
if (const auto *CID = PID->getClassInterface())
|
|
|
|
Out << *CID;
|
|
|
|
else
|
|
|
|
Out << "<<error-type>>";
|
|
|
|
Out << '(' << *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) {
|
2020-07-10 05:32:05 +08:00
|
|
|
Out << "@interface ";
|
|
|
|
if (const auto *CID = PID->getClassInterface())
|
|
|
|
Out << *CID;
|
|
|
|
else
|
|
|
|
Out << "<<error-type>>";
|
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
|
|
|
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";
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
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.
|
|
|
|
///
|
2019-04-09 03:52:45 +08:00
|
|
|
/// Print attributes in the following order:
|
|
|
|
/// - class
|
|
|
|
/// - nonatomic | atomic
|
|
|
|
/// - assign | retain | strong | copy | weak | unsafe_unretained
|
|
|
|
/// - readwrite | readonly
|
|
|
|
/// - getter & setter
|
|
|
|
/// - nullability
|
2009-05-30 08:08:05 +08:00
|
|
|
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";
|
2020-04-23 14:20:56 +08:00
|
|
|
if (PDecl->getPropertyAttributes() != ObjCPropertyAttribute::kind_noattr) {
|
2009-05-30 08:08:05 +08:00
|
|
|
bool first = true;
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << "(";
|
2020-04-23 14:20:56 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_class) {
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << (first ? "" : ", ") << "class";
|
2009-05-30 08:08:05 +08:00
|
|
|
first = false;
|
2011-08-18 05:09:35 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2020-04-23 14:20:56 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_direct) {
|
Implement __attribute__((objc_direct)), __attribute__((objc_direct_members))
__attribute__((objc_direct)) is an attribute on methods declaration, and
__attribute__((objc_direct_members)) on implementation, categories or
extensions.
A `direct` property specifier is added (@property(direct) type name)
These attributes / specifiers cause the method to have no associated
Objective-C metadata (for the property or the method itself), and the
calling convention to be a direct C function call.
The symbol for the method has enforced hidden visibility and such direct
calls are hence unreachable cross image. An explicit C function must be
made if so desired to wrap them.
The implicit `self` and `_cmd` arguments are preserved, however to
maintain compatibility with the usual `objc_msgSend` semantics,
3 fundamental precautions are taken:
1) for instance methods, `self` is nil-checked. On arm64 backends this
typically adds a single instruction (cbz x0, <closest-ret>) to the
codegen, for the vast majority of the cases when the return type is a
scalar.
2) for class methods, because the class may not be realized/initialized
yet, a call to `[self self]` is emitted. When the proper deployment
target is used, this is optimized to `objc_opt_self(self)`.
However, long term we might want to emit something better that the
optimizer can reason about. When inlining kicks in, these calls
aren't optimized away as the optimizer has no idea that a single call
is really necessary.
3) the calling convention for the `_cmd` argument is changed: the caller
leaves the second argument to the call undefined, and the selector is
loaded inside the body when it's referenced only.
As far as error reporting goes, the compiler refuses:
- making any overloads direct,
- making an overload of a direct method,
- implementations marked as direct when the declaration in the
interface isn't (the other way around is allowed, as the direct
attribute is inherited from the declaration),
- marking methods required for protocol conformance as direct,
- messaging an unqualified `id` with a direct method,
- forming any @selector() expression with only direct selectors.
As warnings:
- any inconsistency of direct-related calling convention when
@selector() or messaging is used,
- forming any @selector() expression with a possibly direct selector.
Lastly an `objc_direct_members` attribute is added that can decorate
`@implementation` blocks and causes methods only declared there (and in
no `@interface`) to be automatically direct. When decorating an
`@interface` then all methods and properties declared in this block are
marked direct.
Radar-ID: rdar://problem/2684889
Differential Revision: https://reviews.llvm.org/D69991
Reviewed-By: John McCall
2019-11-08 15:14:58 +08:00
|
|
|
Out << (first ? "" : ", ") << "direct";
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
|
2019-04-09 03:52:45 +08:00
|
|
|
if (PDecl->getPropertyAttributes() &
|
2020-04-23 14:20:56 +08:00
|
|
|
ObjCPropertyAttribute::kind_nonatomic) {
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << (first ? "" : ", ") << "nonatomic";
|
2011-08-18 05:09:35 +08:00
|
|
|
first = false;
|
|
|
|
}
|
2020-04-23 14:20:56 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_atomic) {
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << (first ? "" : ", ") << "atomic";
|
2011-08-18 05:09:35 +08:00
|
|
|
first = false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2020-04-23 14:20:56 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_assign) {
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << (first ? "" : ", ") << "assign";
|
2011-08-18 05:09:35 +08:00
|
|
|
first = false;
|
|
|
|
}
|
2020-04-23 14:20:56 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_retain) {
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << (first ? "" : ", ") << "retain";
|
2011-08-18 05:09:35 +08:00
|
|
|
first = false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2020-04-23 14:20:56 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_strong) {
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << (first ? "" : ", ") << "strong";
|
2011-08-18 05:09:35 +08:00
|
|
|
first = false;
|
|
|
|
}
|
2020-04-23 14:20:56 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_copy) {
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << (first ? "" : ", ") << "copy";
|
|
|
|
first = false;
|
|
|
|
}
|
2020-04-23 14:20:56 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_weak) {
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << (first ? "" : ", ") << "weak";
|
|
|
|
first = false;
|
|
|
|
}
|
2020-04-23 14:20:56 +08:00
|
|
|
if (PDecl->getPropertyAttributes() &
|
|
|
|
ObjCPropertyAttribute::kind_unsafe_unretained) {
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << (first ? "" : ", ") << "unsafe_unretained";
|
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() &
|
2020-04-23 14:20:56 +08:00
|
|
|
ObjCPropertyAttribute::kind_readwrite) {
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << (first ? "" : ", ") << "readwrite";
|
2011-08-18 05:09:35 +08:00
|
|
|
first = false;
|
|
|
|
}
|
2020-04-23 14:20:56 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly) {
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << (first ? "" : ", ") << "readonly";
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
|
2020-04-23 14:20:56 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_getter) {
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << (first ? "" : ", ") << "getter = ";
|
|
|
|
PDecl->getGetterName().print(Out);
|
|
|
|
first = false;
|
|
|
|
}
|
2020-04-23 14:20:56 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyAttribute::kind_setter) {
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << (first ? "" : ", ") << "setter = ";
|
|
|
|
PDecl->getSetterName().print(Out);
|
2011-08-18 05:09:35 +08:00
|
|
|
first = false;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2015-06-20 02:14:38 +08:00
|
|
|
if (PDecl->getPropertyAttributes() &
|
2020-04-23 14:20:56 +08:00
|
|
|
ObjCPropertyAttribute::kind_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() &
|
2020-04-23 14:20:56 +08:00
|
|
|
ObjCPropertyAttribute::kind_null_resettable)) {
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << (first ? "" : ", ") << "null_resettable";
|
2015-06-20 02:14:46 +08:00
|
|
|
} else {
|
2019-04-09 03:52:45 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-18 05:09:35 +08:00
|
|
|
(void) first; // Silence dead store warning due to idiomatic code.
|
2019-04-09 03:52:45 +08:00
|
|
|
Out << ")";
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
2019-04-09 03:52:45 +08:00
|
|
|
std::string TypeStr = PDecl->getASTContext().getUnqualifiedObjCPointerType(T).
|
|
|
|
getAsString(Policy);
|
|
|
|
Out << ' ' << TypeStr;
|
|
|
|
if (!StringRef(TypeStr).endswith("*"))
|
|
|
|
Out << ' ';
|
|
|
|
Out << *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
|
|
|
}
|
|
|
|
|
2021-05-05 23:55:02 +08:00
|
|
|
void DeclPrinter::VisitUsingEnumDecl(UsingEnumDecl *D) {
|
|
|
|
Out << "using enum " << D->getEnumDecl();
|
|
|
|
}
|
|
|
|
|
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 << ")";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-08 01:54:44 +08:00
|
|
|
void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
|
|
|
|
Out << "#pragma omp allocate";
|
|
|
|
if (!D->varlist_empty()) {
|
|
|
|
for (OMPAllocateDecl::varlist_iterator I = D->varlist_begin(),
|
|
|
|
E = D->varlist_end();
|
|
|
|
I != E; ++I) {
|
|
|
|
Out << (I == D->varlist_begin() ? '(' : ',');
|
|
|
|
NamedDecl *ND = cast<DeclRefExpr>(*I)->getDecl();
|
|
|
|
ND->printQualifiedName(Out);
|
|
|
|
}
|
|
|
|
Out << ")";
|
|
|
|
}
|
2019-03-13 02:52:33 +08:00
|
|
|
if (!D->clauselist_empty()) {
|
|
|
|
OMPClausePrinter Printer(Out, Policy);
|
2021-11-09 20:33:39 +08:00
|
|
|
for (OMPClause *C : D->clauselists()) {
|
|
|
|
Out << " ";
|
2019-03-13 02:52:33 +08:00
|
|
|
Printer.Visit(C);
|
2021-11-09 20:33:39 +08:00
|
|
|
}
|
2019-03-13 02:52:33 +08:00
|
|
|
}
|
2019-03-08 01:54:44 +08:00
|
|
|
}
|
|
|
|
|
2018-09-26 12:28:39 +08:00
|
|
|
void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) {
|
|
|
|
Out << "#pragma omp requires ";
|
|
|
|
if (!D->clauselist_empty()) {
|
2018-11-02 20:18:11 +08:00
|
|
|
OMPClausePrinter Printer(Out, Policy);
|
|
|
|
for (auto I = D->clauselist_begin(), E = D->clauselist_end(); I != E; ++I)
|
|
|
|
Printer.Visit(*I);
|
2018-09-26 12:28:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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) {
|
|
|
|
const char *OpName =
|
2019-06-15 04:01:51 +08:00
|
|
|
getOperatorSpelling(D->getDeclName().getCXXOverloadedOperator());
|
2016-03-03 13:21:39 +08:00
|
|
|
assert(OpName && "not an overloaded operator");
|
|
|
|
Out << OpName;
|
|
|
|
} else {
|
|
|
|
assert(D->getDeclName().isIdentifier());
|
|
|
|
D->printName(Out);
|
|
|
|
}
|
|
|
|
Out << " : ";
|
|
|
|
D->getType().print(Out, Policy);
|
|
|
|
Out << " : ";
|
2021-02-19 20:14:55 +08:00
|
|
|
D->getCombiner()->printPretty(Out, nullptr, Policy, 0, "\n", &Context);
|
2016-03-03 13:21:39 +08:00
|
|
|
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;
|
|
|
|
}
|
2021-02-19 20:14:55 +08:00
|
|
|
Init->printPretty(Out, nullptr, Policy, 0, "\n", &Context);
|
2017-09-06 22:49:58 +08:00
|
|
|
if (D->getInitializerKind() == OMPDeclareReductionDecl::DirectInit)
|
|
|
|
Out << ")";
|
2016-03-03 13:21:39 +08:00
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-02 04:25:04 +08:00
|
|
|
void DeclPrinter::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) {
|
|
|
|
if (!D->isInvalidDecl()) {
|
|
|
|
Out << "#pragma omp declare mapper (";
|
|
|
|
D->printName(Out);
|
|
|
|
Out << " : ";
|
|
|
|
D->getType().print(Out, Policy);
|
|
|
|
Out << " ";
|
|
|
|
Out << D->getVarName();
|
|
|
|
Out << ")";
|
|
|
|
if (!D->clauselist_empty()) {
|
|
|
|
OMPClausePrinter Printer(Out, Policy);
|
|
|
|
for (auto *C : D->clauselists()) {
|
|
|
|
Out << " ";
|
|
|
|
Printer.Visit(C);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 13:35:55 +08:00
|
|
|
void DeclPrinter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
|
2021-02-19 20:14:55 +08:00
|
|
|
D->getInit()->printPretty(Out, nullptr, Policy, Indentation, "\n", &Context);
|
2016-02-08 17:29:13 +08:00
|
|
|
}
|
|
|
|
|
2020-01-30 21:00:51 +08:00
|
|
|
void DeclPrinter::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP) {
|
|
|
|
if (const TypeConstraint *TC = TTP->getTypeConstraint())
|
|
|
|
TC->print(Out, Policy);
|
|
|
|
else if (TTP->wasDeclaredWithTypename())
|
|
|
|
Out << "typename";
|
|
|
|
else
|
|
|
|
Out << "class";
|
|
|
|
|
|
|
|
if (TTP->isParameterPack())
|
|
|
|
Out << " ...";
|
2020-08-05 19:10:16 +08:00
|
|
|
else if (TTP->getDeclName())
|
2020-01-30 21:00:51 +08:00
|
|
|
Out << ' ';
|
|
|
|
|
2021-12-30 08:57:47 +08:00
|
|
|
if (TTP->getDeclName()) {
|
|
|
|
if (Policy.CleanUglifiedParameters && TTP->getIdentifier())
|
|
|
|
Out << TTP->getIdentifier()->deuglifiedName();
|
|
|
|
else
|
|
|
|
Out << TTP->getDeclName();
|
|
|
|
}
|
2020-01-30 21:00:51 +08:00
|
|
|
|
|
|
|
if (TTP->hasDefaultArgument()) {
|
|
|
|
Out << " = ";
|
|
|
|
Out << TTP->getDefaultArgument().getAsString(Policy);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitNonTypeTemplateParmDecl(
|
|
|
|
const NonTypeTemplateParmDecl *NTTP) {
|
|
|
|
StringRef Name;
|
|
|
|
if (IdentifierInfo *II = NTTP->getIdentifier())
|
2021-12-30 08:57:47 +08:00
|
|
|
Name =
|
|
|
|
Policy.CleanUglifiedParameters ? II->deuglifiedName() : II->getName();
|
2020-01-30 21:00:51 +08:00
|
|
|
printDeclType(NTTP->getType(), Name, NTTP->isParameterPack());
|
|
|
|
|
|
|
|
if (NTTP->hasDefaultArgument()) {
|
|
|
|
Out << " = ";
|
2021-02-19 20:14:55 +08:00
|
|
|
NTTP->getDefaultArgument()->printPretty(Out, nullptr, Policy, Indentation,
|
|
|
|
"\n", &Context);
|
2020-01-30 21:00:51 +08:00
|
|
|
}
|
|
|
|
}
|