2009-05-30 08:08:05 +08:00
|
|
|
//===--- DeclPrinter.cpp - Printing implementation for Decl ASTs ----------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the Decl::dump method, which pretty print the
|
|
|
|
// AST back out to C/Objective-C/C++/Objective-C++ code.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/AST/ASTContext.h"
|
|
|
|
#include "clang/AST/DeclVisitor.h"
|
|
|
|
#include "clang/AST/Decl.h"
|
|
|
|
#include "clang/AST/DeclCXX.h"
|
|
|
|
#include "clang/AST/DeclObjC.h"
|
|
|
|
#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"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
namespace {
|
2009-11-29 03:03:38 +08:00
|
|
|
class DeclPrinter : public DeclVisitor<DeclPrinter> {
|
2009-05-30 08:08:05 +08:00
|
|
|
llvm::raw_ostream &Out;
|
|
|
|
ASTContext &Context;
|
|
|
|
PrintingPolicy Policy;
|
|
|
|
unsigned Indentation;
|
|
|
|
|
2009-11-21 17:12:06 +08:00
|
|
|
llvm::raw_ostream& Indent() { return Indent(Indentation); }
|
|
|
|
llvm::raw_ostream& Indent(unsigned Indentation);
|
2009-05-30 12:20:30 +08:00
|
|
|
void ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls);
|
2009-05-30 08:08:05 +08:00
|
|
|
|
2009-08-29 06:39:52 +08:00
|
|
|
void Print(AccessSpecifier AS);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
public:
|
2009-09-09 23:08:12 +08:00
|
|
|
DeclPrinter(llvm::raw_ostream &Out, ASTContext &Context,
|
2009-05-30 08:08:05 +08:00
|
|
|
const PrintingPolicy &Policy,
|
|
|
|
unsigned Indentation = 0)
|
|
|
|
: Out(Out), Context(Context), Policy(Policy), Indentation(Indentation) { }
|
|
|
|
|
|
|
|
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);
|
|
|
|
void VisitFunctionDecl(FunctionDecl *D);
|
|
|
|
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-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);
|
2009-05-30 08:08:05 +08:00
|
|
|
void VisitObjCMethodDecl(ObjCMethodDecl *D);
|
2009-05-30 14:31:56 +08:00
|
|
|
void VisitObjCClassDecl(ObjCClassDecl *D);
|
2009-05-30 08:08:05 +08:00
|
|
|
void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
|
|
|
|
void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
|
|
|
|
void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
|
|
|
|
void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
|
|
|
|
void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
|
|
|
|
void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
|
|
|
|
void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
|
|
|
|
void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
|
|
|
|
void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
|
2009-11-18 10:36:19 +08:00
|
|
|
void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
|
|
|
|
void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
|
2009-08-29 03:16:39 +08:00
|
|
|
void VisitUsingDecl(UsingDecl *D);
|
2009-11-17 13:59:44 +08:00
|
|
|
void VisitUsingShadowDecl(UsingShadowDecl *D);
|
2009-05-30 08:08:05 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2009-09-27 05:58:53 +08:00
|
|
|
void Decl::print(llvm::raw_ostream &Out, unsigned Indentation) const {
|
2009-06-30 10:35:04 +08:00
|
|
|
print(Out, getASTContext().PrintingPolicy, Indentation);
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
2009-06-30 10:35:04 +08:00
|
|
|
void Decl::print(llvm::raw_ostream &Out, const PrintingPolicy &Policy,
|
2009-09-27 05:58:53 +08:00
|
|
|
unsigned Indentation) const {
|
2009-06-30 10:35:04 +08:00
|
|
|
DeclPrinter Printer(Out, getASTContext(), Policy, Indentation);
|
2009-09-27 05:58:53 +08:00
|
|
|
Printer.Visit(const_cast<Decl*>(this));
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
2009-05-30 12:20:30 +08:00
|
|
|
static QualType GetBaseType(QualType T) {
|
|
|
|
// FIXME: This should be on the Type class!
|
|
|
|
QualType BaseType = T;
|
|
|
|
while (!BaseType->isSpecifierType()) {
|
|
|
|
if (isa<TypedefType>(BaseType))
|
|
|
|
break;
|
2009-07-30 05:53:49 +08:00
|
|
|
else if (const PointerType* PTy = BaseType->getAs<PointerType>())
|
2009-05-30 12:20:30 +08:00
|
|
|
BaseType = PTy->getPointeeType();
|
|
|
|
else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType))
|
|
|
|
BaseType = ATy->getElementType();
|
2009-09-22 07:43:11 +08:00
|
|
|
else if (const FunctionType* FTy = BaseType->getAs<FunctionType>())
|
2009-05-30 12:20:30 +08:00
|
|
|
BaseType = FTy->getResultType();
|
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();
|
2009-05-30 12:20:30 +08:00
|
|
|
else
|
|
|
|
assert(0 && "Unknown declarator!");
|
|
|
|
}
|
|
|
|
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,
|
2009-06-30 10:35:04 +08:00
|
|
|
llvm::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);
|
|
|
|
if (TD && TD->isDefinition()) {
|
2009-06-30 10:35:04 +08:00
|
|
|
TD->print(Out, Policy, Indentation);
|
2009-05-30 12:20:30 +08:00
|
|
|
Out << " ";
|
|
|
|
SubPolicy.SuppressTag = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isFirst = true;
|
|
|
|
for ( ; Begin != End; ++Begin) {
|
|
|
|
if (isFirst) {
|
|
|
|
SubPolicy.SuppressSpecifiers = false;
|
|
|
|
isFirst = false;
|
|
|
|
} else {
|
|
|
|
if (!isFirst) Out << ", ";
|
|
|
|
SubPolicy.SuppressSpecifiers = true;
|
|
|
|
}
|
|
|
|
|
2009-06-30 10:35:04 +08:00
|
|
|
(*Begin)->print(Out, SubPolicy, Indentation);
|
2009-05-30 12:20:30 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-14 08:51:04 +08:00
|
|
|
void DeclContext::dumpDeclContext() const {
|
2009-12-10 01:27:46 +08:00
|
|
|
// Get the translation unit
|
|
|
|
const DeclContext *DC = this;
|
|
|
|
while (!DC->isTranslationUnit())
|
|
|
|
DC = DC->getParent();
|
|
|
|
|
|
|
|
ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
|
|
|
|
DeclPrinter Printer(llvm::errs(), Ctx, Ctx.PrintingPolicy, 0);
|
|
|
|
Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false);
|
|
|
|
}
|
|
|
|
|
2009-09-27 05:58:53 +08:00
|
|
|
void Decl::dump() const {
|
2009-06-30 10:35:04 +08:00
|
|
|
print(llvm::errs());
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
2009-11-21 17:12:06 +08:00
|
|
|
llvm::raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
|
|
|
|
for (unsigned i = 0; i != Indentation; ++i)
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << " ";
|
|
|
|
return Out;
|
|
|
|
}
|
|
|
|
|
2009-05-30 12:20:30 +08:00
|
|
|
void DeclPrinter::ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls) {
|
|
|
|
this->Indent();
|
2009-06-30 10:35:04 +08:00
|
|
|
Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
|
2009-05-30 12:20:30 +08:00
|
|
|
Out << ";\n";
|
|
|
|
Decls.clear();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-08-29 06:39:52 +08:00
|
|
|
void DeclPrinter::Print(AccessSpecifier AS) {
|
|
|
|
switch(AS) {
|
2009-08-30 04:36:12 +08:00
|
|
|
case AS_none: assert(0 && "No access specifier!"); break;
|
2009-08-29 06:39:52 +08:00
|
|
|
case AS_public: Out << "public"; break;
|
|
|
|
case AS_protected: Out << "protected"; break;
|
2010-06-05 13:09:32 +08:00
|
|
|
case AS_private: Out << "private"; break;
|
2009-08-29 06:39:52 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// Common C declarations
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
|
|
|
|
if (Indent)
|
|
|
|
Indentation += Policy.Indentation;
|
|
|
|
|
2009-05-30 12:20:30 +08:00
|
|
|
llvm::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;
|
|
|
|
|
2009-05-30 13:03:24 +08:00
|
|
|
if (!Policy.Dump) {
|
|
|
|
// Skip over implicit declarations in pretty-printing mode.
|
|
|
|
if (D->isImplicit()) continue;
|
2009-05-30 14:35:22 +08:00
|
|
|
// FIXME: Ugly hack so we don't pretty-print the builtin declaration
|
2010-06-17 18:52:11 +08:00
|
|
|
// of __builtin_va_list or __[u]int128_t. There should be some other way
|
|
|
|
// to check that.
|
|
|
|
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) {
|
|
|
|
if (IdentifierInfo *II = ND->getIdentifier()) {
|
|
|
|
if (II->isStr("__builtin_va_list") ||
|
|
|
|
II->isStr("__int128_t") || II->isStr("__uint128_t"))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2009-05-30 13:03:24 +08:00
|
|
|
}
|
|
|
|
|
2009-05-30 12:20:30 +08:00
|
|
|
// The next bits of code handles stuff like "struct {int x;} a,b"; we're
|
|
|
|
// forced to merge the declarations because there's no other way to
|
|
|
|
// refer to the struct in question. This limited merging is safe without
|
|
|
|
// a bunch of other checks because it only merges declarations directly
|
|
|
|
// referring to the tag, not typedefs.
|
|
|
|
//
|
|
|
|
// Check whether the current declaration should be grouped with a previous
|
|
|
|
// unnamed struct.
|
|
|
|
QualType CurDeclType = getDeclType(*D);
|
|
|
|
if (!Decls.empty() && !CurDeclType.isNull()) {
|
|
|
|
QualType BaseType = GetBaseType(CurDeclType);
|
|
|
|
if (!BaseType.isNull() && isa<TagType>(BaseType) &&
|
|
|
|
cast<TagType>(BaseType)->getDecl() == Decls[0]) {
|
|
|
|
Decls.push_back(*D);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we have a merged group waiting to be handled, handle it now.
|
|
|
|
if (!Decls.empty())
|
|
|
|
ProcessDeclGroup(Decls);
|
|
|
|
|
|
|
|
// If the current declaration is an unnamed tag type, save it
|
|
|
|
// so we can merge it with the subsequent declaration(s) using it.
|
|
|
|
if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) {
|
|
|
|
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
|
2009-05-30 08:08:05 +08:00
|
|
|
const char *Terminator = 0;
|
2009-09-09 23:08:12 +08:00
|
|
|
if (isa<FunctionDecl>(*D) &&
|
2009-05-30 08:08:05 +08:00
|
|
|
cast<FunctionDecl>(*D)->isThisDeclarationADefinition())
|
|
|
|
Terminator = 0;
|
2009-05-30 08:56:08 +08:00
|
|
|
else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody())
|
|
|
|
Terminator = 0;
|
|
|
|
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))
|
2009-05-30 08:08:05 +08:00
|
|
|
Terminator = 0;
|
|
|
|
else if (isa<EnumConstantDecl>(*D)) {
|
|
|
|
DeclContext::decl_iterator Next = D;
|
|
|
|
++Next;
|
|
|
|
if (Next != DEnd)
|
|
|
|
Terminator = ",";
|
|
|
|
} else
|
|
|
|
Terminator = ";";
|
|
|
|
|
|
|
|
if (Terminator)
|
|
|
|
Out << Terminator;
|
|
|
|
Out << "\n";
|
|
|
|
}
|
|
|
|
|
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) {
|
|
|
|
std::string S = D->getNameAsString();
|
|
|
|
D->getUnderlyingType().getAsStringInternal(S, Policy);
|
2009-05-30 12:20:30 +08:00
|
|
|
if (!Policy.SuppressSpecifiers)
|
|
|
|
Out << "typedef ";
|
|
|
|
Out << S;
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
2011-04-15 22:24:37 +08:00
|
|
|
void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
|
|
|
|
Out << "using " << D->getNameAsString() << " = "
|
|
|
|
<< D->getUnderlyingType().getAsString(Policy);
|
|
|
|
}
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
|
2010-12-02 00:01:08 +08:00
|
|
|
Out << "enum ";
|
2010-12-04 02:54:17 +08:00
|
|
|
if (D->isScoped()) {
|
|
|
|
if (D->isScopedUsingClassTag())
|
|
|
|
Out << "class ";
|
|
|
|
else
|
|
|
|
Out << "struct ";
|
|
|
|
}
|
2010-12-02 00:01:08 +08:00
|
|
|
Out << D;
|
|
|
|
|
|
|
|
if (D->isFixed()) {
|
|
|
|
std::string Underlying;
|
|
|
|
D->getIntegerType().getAsStringInternal(Underlying, Policy);
|
|
|
|
Out << " : " << Underlying;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (D->isDefinition()) {
|
|
|
|
Out << " {\n";
|
|
|
|
VisitDeclContext(D);
|
|
|
|
Indent() << "}";
|
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
|
|
|
|
Out << D->getKindName();
|
2010-04-17 17:33:03 +08:00
|
|
|
if (D->getIdentifier())
|
|
|
|
Out << ' ' << D;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (D->isDefinition()) {
|
|
|
|
Out << " {\n";
|
|
|
|
VisitDeclContext(D);
|
|
|
|
Indent() << "}";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << D;
|
2009-05-30 08:08:05 +08:00
|
|
|
if (Expr *Init = D->getInitExpr()) {
|
|
|
|
Out << " = ";
|
2009-05-30 13:03:24 +08:00
|
|
|
Init->printPretty(Out, Context, 0, Policy, Indentation);
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
2009-05-30 12:20:30 +08:00
|
|
|
if (!Policy.SuppressSpecifiers) {
|
|
|
|
switch (D->getStorageClass()) {
|
2010-08-26 11:08:43 +08:00
|
|
|
case SC_None: break;
|
|
|
|
case SC_Extern: Out << "extern "; break;
|
|
|
|
case SC_Static: Out << "static "; break;
|
|
|
|
case SC_PrivateExtern: Out << "__private_extern__ "; break;
|
|
|
|
case SC_Auto: case SC_Register: llvm_unreachable("invalid for functions");
|
2009-05-30 12:20:30 +08:00
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
|
2009-10-28 05:01:01 +08:00
|
|
|
if (D->isInlineSpecified()) Out << "inline ";
|
2009-05-30 12:20:30 +08:00
|
|
|
if (D->isVirtualAsWritten()) Out << "virtual ";
|
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
|
2009-05-30 13:39:39 +08:00
|
|
|
PrintingPolicy SubPolicy(Policy);
|
|
|
|
SubPolicy.SuppressSpecifiers = false;
|
2010-08-12 06:01:17 +08:00
|
|
|
std::string Proto = D->getNameInfo().getAsString();
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isa<FunctionType>(Ty)) {
|
|
|
|
const FunctionType *AFT = Ty->getAs<FunctionType>();
|
2009-05-30 08:08:05 +08:00
|
|
|
const FunctionProtoType *FT = 0;
|
|
|
|
if (D->hasWrittenPrototype())
|
|
|
|
FT = dyn_cast<FunctionProtoType>(AFT);
|
|
|
|
|
|
|
|
Proto += "(";
|
|
|
|
if (FT) {
|
|
|
|
llvm::raw_string_ostream POut(Proto);
|
2009-05-30 13:39:39 +08:00
|
|
|
DeclPrinter ParamPrinter(POut, Context, SubPolicy, Indentation);
|
2009-05-30 08:08:05 +08:00
|
|
|
for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
|
|
|
|
if (i) POut << ", ";
|
|
|
|
ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (FT->isVariadic()) {
|
|
|
|
if (D->getNumParams()) POut << ", ";
|
|
|
|
POut << "...";
|
|
|
|
}
|
2011-05-07 04:44:56 +08:00
|
|
|
} else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) {
|
2009-05-30 12:20:30 +08:00
|
|
|
for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
|
|
|
|
if (i)
|
|
|
|
Proto += ", ";
|
|
|
|
Proto += D->getParamDecl(i)->getNameAsString();
|
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Proto += ")";
|
2009-12-09 01:45:32 +08:00
|
|
|
|
2010-11-20 02:44:34 +08:00
|
|
|
if (FT && FT->getTypeQuals()) {
|
|
|
|
unsigned TypeQuals = FT->getTypeQuals();
|
|
|
|
if (TypeQuals & Qualifiers::Const)
|
|
|
|
Proto += " const";
|
|
|
|
if (TypeQuals & Qualifiers::Volatile)
|
|
|
|
Proto += " volatile";
|
|
|
|
if (TypeQuals & Qualifiers::Restrict)
|
|
|
|
Proto += " restrict";
|
|
|
|
}
|
2011-03-12 19:50:43 +08:00
|
|
|
|
|
|
|
if (FT && FT->hasDynamicExceptionSpec()) {
|
2009-12-09 01:45:32 +08:00
|
|
|
Proto += " throw(";
|
2011-03-12 19:50:43 +08:00
|
|
|
if (FT->getExceptionSpecType() == EST_MSAny)
|
2009-12-09 01:45:32 +08:00
|
|
|
Proto += "...";
|
|
|
|
else
|
|
|
|
for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) {
|
|
|
|
if (I)
|
|
|
|
Proto += ", ";
|
2011-03-12 19:50:43 +08:00
|
|
|
|
2009-12-09 01:45:32 +08:00
|
|
|
std::string ExceptionType;
|
|
|
|
FT->getExceptionType(I).getAsStringInternal(ExceptionType, SubPolicy);
|
|
|
|
Proto += ExceptionType;
|
|
|
|
}
|
|
|
|
Proto += ")";
|
2011-03-12 19:50:43 +08:00
|
|
|
} else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) {
|
|
|
|
Proto += " noexcept";
|
|
|
|
if (FT->getExceptionSpecType() == EST_ComputedNoexcept) {
|
|
|
|
Proto += "(";
|
|
|
|
llvm::raw_string_ostream EOut(Proto);
|
|
|
|
FT->getNoexceptExpr()->printPretty(EOut, Context, 0, SubPolicy,
|
|
|
|
Indentation);
|
|
|
|
EOut.flush();
|
|
|
|
Proto += EOut.str();
|
|
|
|
Proto += ")";
|
|
|
|
}
|
2009-12-09 01:45:32 +08:00
|
|
|
}
|
|
|
|
|
2009-07-28 05:33:40 +08:00
|
|
|
if (D->hasAttr<NoReturnAttr>())
|
|
|
|
Proto += " __attribute((noreturn))";
|
2009-07-14 04:18:13 +08:00
|
|
|
if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) {
|
2011-06-12 01:19:42 +08:00
|
|
|
bool HasInitializerList = false;
|
|
|
|
for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(),
|
|
|
|
E = CDecl->init_end();
|
|
|
|
B != E; ++B) {
|
|
|
|
CXXCtorInitializer * BMInitializer = (*B);
|
|
|
|
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();
|
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
|
|
|
|
2011-06-12 01:19:42 +08:00
|
|
|
Expr *SimpleInit = 0;
|
|
|
|
Expr **Args = 0;
|
|
|
|
unsigned NumArgs = 0;
|
|
|
|
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
|
|
|
|
Args = ParenList->getExprs();
|
|
|
|
NumArgs = ParenList->getNumExprs();
|
|
|
|
} else if (CXXConstructExpr *Construct
|
|
|
|
= dyn_cast<CXXConstructExpr>(Init)) {
|
|
|
|
Args = Construct->getArgs();
|
|
|
|
NumArgs = Construct->getNumArgs();
|
|
|
|
} else
|
|
|
|
SimpleInit = Init;
|
|
|
|
|
|
|
|
if (SimpleInit)
|
|
|
|
SimpleInit->printPretty(Out, Context, 0, Policy, Indentation);
|
|
|
|
else {
|
|
|
|
for (unsigned I = 0; I != NumArgs; ++I) {
|
|
|
|
if (isa<CXXDefaultArgExpr>(Args[I]))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (I)
|
|
|
|
Out << ", ";
|
|
|
|
Args[I]->printPretty(Out, Context, 0, Policy, Indentation);
|
2009-07-14 04:18:13 +08:00
|
|
|
}
|
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
|
|
|
}
|
2009-07-14 04:18:13 +08:00
|
|
|
}
|
2011-06-12 01:19:42 +08:00
|
|
|
Out << ")";
|
2009-07-14 04:18:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
AFT->getResultType().getAsStringInternal(Proto, Policy);
|
2009-05-30 08:08:05 +08:00
|
|
|
} else {
|
2010-12-15 06:11:44 +08:00
|
|
|
Ty.getAsStringInternal(Proto, Policy);
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Out << Proto;
|
|
|
|
|
|
|
|
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";
|
2011-05-07 04:44:56 +08:00
|
|
|
else if (D->doesThisDeclarationHaveABody()) {
|
2009-05-30 08:08:05 +08:00
|
|
|
if (!D->hasPrototype() && D->getNumParams()) {
|
|
|
|
// This is a K&R function definition, so we need to print the
|
|
|
|
// parameters.
|
|
|
|
Out << '\n';
|
2009-05-30 13:39:39 +08:00
|
|
|
DeclPrinter ParamPrinter(Out, Context, SubPolicy, Indentation);
|
2009-05-30 08:08:05 +08:00
|
|
|
Indentation += Policy.Indentation;
|
|
|
|
for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
|
|
|
|
Indent();
|
2009-05-30 13:39:39 +08:00
|
|
|
ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << ";\n";
|
|
|
|
}
|
|
|
|
Indentation -= Policy.Indentation;
|
|
|
|
} else
|
|
|
|
Out << ' ';
|
|
|
|
|
2009-06-30 10:35:26 +08:00
|
|
|
D->getBody()->printPretty(Out, Context, 0, SubPolicy, Indentation);
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << '\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
|
2009-05-30 12:20:30 +08:00
|
|
|
if (!Policy.SuppressSpecifiers && D->isMutable())
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << "mutable ";
|
|
|
|
|
|
|
|
std::string Name = D->getNameAsString();
|
|
|
|
D->getType().getAsStringInternal(Name, Policy);
|
|
|
|
Out << Name;
|
|
|
|
|
|
|
|
if (D->isBitField()) {
|
|
|
|
Out << " : ";
|
2009-05-30 13:03:24 +08:00
|
|
|
D->getBitWidth()->printPretty(Out, Context, 0, Policy, Indentation);
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
2011-06-12 01:19:42 +08:00
|
|
|
|
|
|
|
Expr *Init = D->getInClassInitializer();
|
|
|
|
if (!Policy.SuppressInitializers && Init) {
|
|
|
|
Out << " = ";
|
|
|
|
Init->printPretty(Out, Context, 0, Policy, Indentation);
|
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
2011-02-18 04:34:02 +08:00
|
|
|
void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
|
|
|
|
Out << D->getNameAsString() << ":";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
void DeclPrinter::VisitVarDecl(VarDecl *D) {
|
2010-08-26 11:08:43 +08:00
|
|
|
if (!Policy.SuppressSpecifiers && D->getStorageClass() != SC_None)
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << VarDecl::getStorageClassSpecifierString(D->getStorageClass()) << " ";
|
|
|
|
|
2009-05-30 12:20:30 +08:00
|
|
|
if (!Policy.SuppressSpecifiers && D->isThreadSpecified())
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << "__thread ";
|
|
|
|
|
|
|
|
std::string Name = D->getNameAsString();
|
|
|
|
QualType T = D->getType();
|
2009-10-24 05:48:59 +08:00
|
|
|
if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D))
|
2009-05-30 08:08:05 +08:00
|
|
|
T = Parm->getOriginalType();
|
|
|
|
T.getAsStringInternal(Name, Policy);
|
|
|
|
Out << Name;
|
2011-04-15 06:09:26 +08:00
|
|
|
Expr *Init = D->getInit();
|
|
|
|
if (!Policy.SuppressInitializers && Init) {
|
2009-05-30 08:08:05 +08:00
|
|
|
if (D->hasCXXDirectInitializer())
|
|
|
|
Out << "(";
|
2010-09-18 07:04:38 +08:00
|
|
|
else {
|
|
|
|
CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init);
|
|
|
|
if (!CCE || CCE->getConstructor()->isCopyConstructor())
|
|
|
|
Out << " = ";
|
|
|
|
}
|
2010-09-08 06:21:59 +08:00
|
|
|
Init->printPretty(Out, Context, 0, Policy, Indentation);
|
2009-05-30 08:08:05 +08:00
|
|
|
if (D->hasCXXDirectInitializer())
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
|
|
|
|
VisitVarDecl(D);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
|
|
|
|
Out << "__asm (";
|
2009-05-30 13:03:24 +08:00
|
|
|
D->getAsmString()->printPretty(Out, Context, 0, Policy, Indentation);
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
2011-03-17 02:37:27 +08:00
|
|
|
void DeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {
|
|
|
|
Out << "static_assert(";
|
|
|
|
D->getAssertExpr()->printPretty(Out, Context, 0, Policy, Indentation);
|
|
|
|
Out << ", ";
|
|
|
|
D->getMessage()->printPretty(Out, Context, 0, Policy, Indentation);
|
|
|
|
Out << ")";
|
|
|
|
}
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// C++ declarations
|
|
|
|
//----------------------------------------------------------------------------
|
2009-05-30 14:58:37 +08:00
|
|
|
void DeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) {
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << "namespace " << D << " {\n";
|
2009-05-30 14:58:37 +08:00
|
|
|
VisitDeclContext(D);
|
|
|
|
Indent() << "}";
|
|
|
|
}
|
|
|
|
|
2009-05-30 14:31:56 +08:00
|
|
|
void DeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
|
|
|
|
Out << "using namespace ";
|
|
|
|
if (D->getQualifier())
|
|
|
|
D->getQualifier()->print(Out, Policy);
|
2010-04-17 17:33:03 +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) {
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << "namespace " << D << " = ";
|
2009-05-30 14:48:27 +08:00
|
|
|
if (D->getQualifier())
|
|
|
|
D->getQualifier()->print(Out, Policy);
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << D->getAliasedNamespace();
|
2009-05-30 14:48:27 +08:00
|
|
|
}
|
|
|
|
|
2009-05-30 14:58:37 +08:00
|
|
|
void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
|
|
|
|
Out << D->getKindName();
|
2010-04-17 17:33:03 +08:00
|
|
|
if (D->getIdentifier())
|
|
|
|
Out << ' ' << D;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 14:58:37 +08:00
|
|
|
if (D->isDefinition()) {
|
|
|
|
// 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();
|
|
|
|
if (AS != AS_none)
|
|
|
|
Print(AS);
|
2009-08-29 06:39:52 +08:00
|
|
|
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:"
|
2009-05-30 14:58:37 +08:00
|
|
|
Out << " {\n";
|
|
|
|
VisitDeclContext(D);
|
|
|
|
Indent() << "}";
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
|
|
|
|
const char *l;
|
|
|
|
if (D->getLanguage() == LinkageSpecDecl::lang_c)
|
|
|
|
l = "C";
|
|
|
|
else {
|
|
|
|
assert(D->getLanguage() == LinkageSpecDecl::lang_cxx &&
|
|
|
|
"unknown language in linkage specification");
|
|
|
|
l = "C++";
|
|
|
|
}
|
|
|
|
|
|
|
|
Out << "extern \"" << l << "\" ";
|
|
|
|
if (D->hasBraces()) {
|
|
|
|
Out << "{\n";
|
|
|
|
VisitDeclContext(D);
|
|
|
|
Indent() << "}";
|
|
|
|
} else
|
2009-06-30 10:36:12 +08:00
|
|
|
Visit(*D->decls_begin());
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
2011-04-15 21:38:57 +08:00
|
|
|
void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
|
2009-06-04 13:37:43 +08:00
|
|
|
Out << "template <";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-04 13:37:43 +08:00
|
|
|
TemplateParameterList *Params = D->getTemplateParameters();
|
|
|
|
for (unsigned i = 0, e = Params->size(); i != e; ++i) {
|
|
|
|
if (i != 0)
|
|
|
|
Out << ", ";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-04 13:37:43 +08:00
|
|
|
const Decl *Param = Params->getParam(i);
|
2009-09-09 23:08:12 +08:00
|
|
|
if (const TemplateTypeParmDecl *TTP =
|
2009-06-04 13:37:43 +08:00
|
|
|
dyn_cast<TemplateTypeParmDecl>(Param)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-04 13:37:43 +08:00
|
|
|
if (TTP->wasDeclaredWithTypename())
|
|
|
|
Out << "typename ";
|
|
|
|
else
|
|
|
|
Out << "class ";
|
|
|
|
|
2009-06-13 06:23:22 +08:00
|
|
|
if (TTP->isParameterPack())
|
|
|
|
Out << "... ";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
Re-applies the patch first applied way back in r106099, with
accompanying fixes to make it work today.
The core of this patch is to provide a link from a TemplateTypeParmType
back to the TemplateTypeParmDecl node which declared it. This in turn
provides much more precise information about the type, where it came
from, and how it functions for AST consumers.
To make the patch work almost a year after its first attempt, it needed
serialization support, and it now retains the old getName() interface.
Finally, it requires us to not attempt to instantiate the type in an
unsupported friend decl -- specifically those coming from template
friend decls but which refer to a specific type through a dependent
name.
A cleaner representation of the last item would be to build
FriendTemplateDecl nodes for these, storing their template parameters
etc, and to perform proper instantation of them like any other template
declaration. They can still be flagged as unsupported for the purpose of
access checking, etc.
This passed an asserts-enabled bootstrap for me, and the reduced test
case mentioned in the original review thread no longer causes issues,
likely fixed at somewhere amidst the 24k revisions that have elapsed.
llvm-svn: 130628
2011-05-01 08:51:33 +08:00
|
|
|
Out << TTP->getNameAsString();
|
2009-06-04 13:37:43 +08:00
|
|
|
|
|
|
|
if (TTP->hasDefaultArgument()) {
|
|
|
|
Out << " = ";
|
|
|
|
Out << TTP->getDefaultArgument().getAsString(Policy);
|
|
|
|
};
|
2009-09-09 23:08:12 +08:00
|
|
|
} else if (const NonTypeTemplateParmDecl *NTTP =
|
2009-06-04 13:37:43 +08:00
|
|
|
dyn_cast<NonTypeTemplateParmDecl>(Param)) {
|
|
|
|
Out << NTTP->getType().getAsString(Policy);
|
|
|
|
|
2010-12-24 08:15:10 +08:00
|
|
|
if (NTTP->isParameterPack() && !isa<PackExpansionType>(NTTP->getType()))
|
|
|
|
Out << "...";
|
|
|
|
|
2009-06-04 13:37:43 +08:00
|
|
|
if (IdentifierInfo *Name = NTTP->getIdentifier()) {
|
|
|
|
Out << ' ';
|
|
|
|
Out << Name->getName();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-04 13:37:43 +08:00
|
|
|
if (NTTP->hasDefaultArgument()) {
|
|
|
|
Out << " = ";
|
2009-09-09 23:08:12 +08:00
|
|
|
NTTP->getDefaultArgument()->printPretty(Out, Context, 0, Policy,
|
2009-06-04 13:37:43 +08:00
|
|
|
Indentation);
|
|
|
|
}
|
2011-04-15 21:38:57 +08:00
|
|
|
} else if (const TemplateTemplateParmDecl *TTPD =
|
|
|
|
dyn_cast<TemplateTemplateParmDecl>(Param)) {
|
|
|
|
VisitTemplateDecl(TTPD);
|
|
|
|
// FIXME: print the default argument, if present.
|
2009-06-04 13:37:43 +08:00
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-04 13:37:43 +08:00
|
|
|
Out << "> ";
|
|
|
|
|
2011-04-15 21:38:57 +08:00
|
|
|
if (const TemplateTemplateParmDecl *TTP =
|
|
|
|
dyn_cast<TemplateTemplateParmDecl>(D)) {
|
2011-01-05 23:48:55 +08:00
|
|
|
Out << "class ";
|
|
|
|
if (TTP->isParameterPack())
|
|
|
|
Out << "...";
|
|
|
|
Out << D->getName();
|
2010-07-10 04:25:10 +08:00
|
|
|
} else {
|
|
|
|
Visit(D->getTemplatedDecl());
|
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// Objective-C declarations
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void DeclPrinter::VisitObjCClassDecl(ObjCClassDecl *D) {
|
|
|
|
Out << "@class ";
|
|
|
|
for (ObjCClassDecl::iterator I = D->begin(), E = D->end();
|
|
|
|
I != E; ++I) {
|
|
|
|
if (I != D->begin()) Out << ", ";
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << I->getInterface();
|
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 << "+ ";
|
2009-05-30 08:08:05 +08:00
|
|
|
if (!OMD->getResultType().isNull())
|
2009-05-30 14:58:37 +08:00
|
|
|
Out << '(' << OMD->getResultType().getAsString(Policy) << ")";
|
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;
|
|
|
|
for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
|
|
|
|
E = OMD->param_end(); PI != E; ++PI) {
|
2009-09-09 23:08:12 +08:00
|
|
|
// FIXME: selector is missing here!
|
2009-05-30 08:08:05 +08:00
|
|
|
pos = name.find_first_of(":", lastPos);
|
|
|
|
Out << " " << name.substr(lastPos, pos - lastPos);
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << ":(" << (*PI)->getType().getAsString(Policy) << ')' << *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())
|
|
|
|
Out << " " << name;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (OMD->isVariadic())
|
|
|
|
Out << ", ...";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (OMD->getBody()) {
|
|
|
|
Out << ' ';
|
2009-05-30 13:03:24 +08:00
|
|
|
OMD->getBody()->printPretty(Out, Context, 0, Policy);
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << '\n';
|
2009-05-30 08:56:08 +08:00
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitObjCImplementationDecl(ObjCImplementationDecl *OID) {
|
|
|
|
std::string I = OID->getNameAsString();
|
|
|
|
ObjCInterfaceDecl *SID = OID->getSuperClass();
|
|
|
|
|
|
|
|
if (SID)
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << "@implementation " << I << " : " << SID;
|
2009-05-30 08:08:05 +08:00
|
|
|
else
|
|
|
|
Out << "@implementation " << I;
|
2009-05-30 08:56:08 +08:00
|
|
|
Out << "\n";
|
|
|
|
VisitDeclContext(OID, false);
|
|
|
|
Out << "@end";
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
|
|
|
|
std::string I = OID->getNameAsString();
|
|
|
|
ObjCInterfaceDecl *SID = OID->getSuperClass();
|
|
|
|
|
|
|
|
if (SID)
|
2010-08-11 20:19:30 +08:00
|
|
|
Out << "@interface " << I << " : " << SID;
|
|
|
|
else
|
|
|
|
Out << "@interface " << I;
|
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)
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << (I == Protocols.begin() ? '<' : ',') << *I;
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (!Protocols.empty())
|
2009-05-30 08:56:08 +08:00
|
|
|
Out << "> ";
|
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";
|
|
|
|
Indentation += Policy.Indentation;
|
2009-05-30 08:08:05 +08:00
|
|
|
for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(),
|
|
|
|
E = OID->ivar_end(); I != E; ++I) {
|
2010-04-17 17:33:03 +08:00
|
|
|
Indent() << (*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";
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
VisitDeclContext(OID, 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::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
|
|
|
|
Out << "@protocol ";
|
2009-09-09 23:08:12 +08:00
|
|
|
for (ObjCForwardProtocolDecl::protocol_iterator I = D->protocol_begin(),
|
2009-05-30 08:08:05 +08:00
|
|
|
E = D->protocol_end();
|
|
|
|
I != E; ++I) {
|
|
|
|
if (I != D->protocol_begin()) Out << ", ";
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << *I;
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
|
2010-04-17 17:33:03 +08:00
|
|
|
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) {
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << "@implementation " << PID->getClassInterface() << '(' << PID << ")\n";
|
2009-05-30 08:08:05 +08:00
|
|
|
|
|
|
|
VisitDeclContext(PID, false);
|
2009-05-30 08:56:08 +08:00
|
|
|
Out << "@end";
|
2009-05-30 08:08:05 +08:00
|
|
|
// FIXME: implement the rest...
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << "@interface " << PID->getClassInterface() << '(' << PID << ")\n";
|
2009-05-30 08:08:05 +08:00
|
|
|
VisitDeclContext(PID, false);
|
2009-05-30 08:56:08 +08:00
|
|
|
Out << "@end";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
// FIXME: implement the rest...
|
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << "@compatibility_alias " << AID
|
|
|
|
<< ' ' << AID->getClassInterface() << ";\n";
|
2009-05-30 08:08:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// PrintObjCPropertyDecl - print a property declaration.
|
|
|
|
///
|
|
|
|
void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
|
|
|
|
if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required)
|
|
|
|
Out << "@required\n";
|
|
|
|
else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
|
|
|
|
Out << "@optional\n";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << "@property";
|
|
|
|
if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
|
|
|
|
bool first = true;
|
|
|
|
Out << " (";
|
2009-09-09 23:08:12 +08:00
|
|
|
if (PDecl->getPropertyAttributes() &
|
2009-05-30 08:08:05 +08:00
|
|
|
ObjCPropertyDecl::OBJC_PR_readonly) {
|
|
|
|
Out << (first ? ' ' : ',') << "readonly";
|
|
|
|
first = false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
|
|
|
|
Out << (first ? ' ' : ',') << "getter = "
|
|
|
|
<< PDecl->getGetterName().getAsString();
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
|
|
|
|
Out << (first ? ' ' : ',') << "setter = "
|
|
|
|
<< PDecl->getSetterName().getAsString();
|
|
|
|
first = false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
|
|
|
|
Out << (first ? ' ' : ',') << "assign";
|
|
|
|
first = false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (PDecl->getPropertyAttributes() &
|
|
|
|
ObjCPropertyDecl::OBJC_PR_readwrite) {
|
|
|
|
Out << (first ? ' ' : ',') << "readwrite";
|
|
|
|
first = false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
|
|
|
|
Out << (first ? ' ' : ',') << "retain";
|
|
|
|
first = false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_strong) {
|
|
|
|
Out << (first ? ' ' : ',') << "strong";
|
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
|
2009-05-30 08:08:05 +08:00
|
|
|
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
|
|
|
|
Out << (first ? ' ' : ',') << "copy";
|
|
|
|
first = false;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
if (PDecl->getPropertyAttributes() &
|
2009-05-30 08:08:05 +08:00
|
|
|
ObjCPropertyDecl::OBJC_PR_nonatomic) {
|
|
|
|
Out << (first ? ' ' : ',') << "nonatomic";
|
|
|
|
first = false;
|
|
|
|
}
|
2011-06-12 01:37:19 +08:00
|
|
|
if (PDecl->getPropertyAttributes() &
|
|
|
|
ObjCPropertyDecl::OBJC_PR_atomic) {
|
|
|
|
Out << (first ? ' ' : ',') << "atomic";
|
|
|
|
first = false;
|
|
|
|
}
|
2009-05-30 08:08:05 +08:00
|
|
|
Out << " )";
|
|
|
|
}
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << ' ' << PDecl->getType().getAsString(Policy) << ' ' << PDecl;
|
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 ";
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << PID->getPropertyDecl();
|
2009-05-30 08:08:05 +08:00
|
|
|
if (PID->getPropertyIvarDecl())
|
2010-04-17 17:33:03 +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) {
|
|
|
|
Out << "using ";
|
2011-02-25 08:36:19 +08:00
|
|
|
D->getQualifier()->print(Out, Policy);
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << D;
|
2009-08-29 03:16:39 +08:00
|
|
|
}
|
|
|
|
|
2009-11-18 10:36:19 +08:00
|
|
|
void
|
|
|
|
DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
|
|
|
|
Out << "using typename ";
|
2011-02-25 08:36:19 +08:00
|
|
|
D->getQualifier()->print(Out, Policy);
|
2010-04-17 17:33:03 +08:00
|
|
|
Out << D->getDeclName();
|
2009-11-18 10:36:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
|
2009-08-29 03:16:39 +08:00
|
|
|
Out << "using ";
|
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-08-29 03:16:39 +08:00
|
|
|
}
|
2009-11-17 13:59:44 +08:00
|
|
|
|
|
|
|
void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
|
|
|
|
// ignore
|
|
|
|
}
|