Generation of forward declarations of top level decls in an input file.
Consists of: ForwardDeclPrinter, adapted from clang::DeclPrinter Interpterer::GenerateAutoloadingMap for invoking the functionality It has hardcoded checks to prevent ForwardDeclPrinter from visiting decls from standard library files. This restriction will be lifted after the issues specifyed in the tests are fixed. Test cases for code which FowrardDeclPrinter can not deal with properly
This commit is contained in:
parent
d42f77918d
commit
f474d63079
@ -21,8 +21,11 @@ namespace cling {
|
||||
Transaction::DelayCallInfo DCI = *I;
|
||||
for (DeclGroupRef::iterator J = DCI.m_DGR.begin(),
|
||||
JE = DCI.m_DGR.end(); J != JE; ++J) {
|
||||
if ( (*J)->hasAttr<AnnotateAttr>() /*FIXME: && CorrectCallbackLoaded() how ? */ )
|
||||
clang::Decl::castToDeclContext(*J)->setHasExternalLexicalStorage();
|
||||
|
||||
//FIXME: Enable when safe !
|
||||
// if ( (*J)->hasAttr<AnnotateAttr>() /*FIXME: && CorrectCallbackLoaded() how ? */ )
|
||||
// clang::Decl::castToDeclContext(*J)->setHasExternalLexicalStorage();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,82 +0,0 @@
|
||||
#include "AutoloadingVisitor.h"
|
||||
namespace cling {
|
||||
bool AutoloadingVisitor::VisitCXXRecordDecl(clang::CXXRecordDecl* Declaration) {
|
||||
if(Declaration->getName().startswith("_")
|
||||
|| Declaration->getName().size() == 0
|
||||
/*|| //TODO: Find a way to avoid templates here*/)
|
||||
return true;
|
||||
|
||||
std::vector<NamespacePrinterRAII> scope;
|
||||
clang::DeclContext* c=Declaration->getEnclosingNamespaceContext();
|
||||
while(c->isNamespace()) {
|
||||
clang::NamespaceDecl* n = llvm::cast<clang::NamespaceDecl>(c);
|
||||
scope.emplace_back(n->getNameAsString());
|
||||
c=c->getParent();
|
||||
}
|
||||
|
||||
llvm::outs() << "\n" << Declaration->getKindName()
|
||||
<< " __attribute__((annotate(\""
|
||||
<< m_InFile << "\"))) "
|
||||
<< Declaration->getName() << ";\n";
|
||||
return true;
|
||||
}
|
||||
bool AutoloadingVisitor::VisitFunctionDecl(clang::FunctionDecl* Declaration) {
|
||||
|
||||
if(Declaration->getName().startswith("_")
|
||||
|| Declaration->getName().size() == 0
|
||||
|| Declaration->isCXXClassMember()
|
||||
|| !Declaration->hasBody())
|
||||
return true;
|
||||
|
||||
std::vector<NamespacePrinterRAII> scope;
|
||||
clang::DeclContext* c = Declaration->getEnclosingNamespaceContext();
|
||||
while(c->isNamespace()) {
|
||||
clang::NamespaceDecl* n = llvm::cast<clang::NamespaceDecl>(c);
|
||||
scope.emplace_back(n->getNameAsString());
|
||||
c=c->getParent();
|
||||
}
|
||||
|
||||
llvm::outs() << "\n" << Declaration->getReturnType().getAsString()
|
||||
<< " " << Declaration->getName() << " () "
|
||||
<< "__attribute__((annotate(\""
|
||||
<< m_InFile << "\")));\n";
|
||||
|
||||
//TODO: arg list, not sure if necessary
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AutoloadingVisitor::VisitClassTemplateDecl
|
||||
(clang::ClassTemplateDecl* Declaration) {
|
||||
if(Declaration->getName().startswith("_")
|
||||
|| Declaration->getName().size() == 0)
|
||||
return true;
|
||||
|
||||
std::vector<NamespacePrinterRAII> scope;
|
||||
clang::DeclContext* c=
|
||||
Declaration->getTemplatedDecl()->getEnclosingNamespaceContext();
|
||||
while(c->isNamespace()) {
|
||||
clang::NamespaceDecl* n = llvm::cast<clang::NamespaceDecl>(c);
|
||||
scope.emplace_back(n->getNameAsString());
|
||||
c=c->getParent();
|
||||
}
|
||||
|
||||
llvm::outs()<<"template <";
|
||||
clang::TemplateParameterList* tl=Declaration->getTemplateParameters();
|
||||
for(auto it=tl->begin();it!=tl->end();++it) {
|
||||
if(llvm::isa<clang::NonTypeTemplateParmDecl>(*it)) {
|
||||
clang::NonTypeTemplateParmDecl* td=llvm::cast<clang::NonTypeTemplateParmDecl>(*it);
|
||||
llvm::outs() << td->getType().getAsString();
|
||||
}
|
||||
else llvm::outs() << "typename";
|
||||
llvm::outs()<<" " << (*it)->getName();
|
||||
if((it+1) != tl->end())
|
||||
llvm::outs() << ", ";
|
||||
}
|
||||
llvm::outs()<<"> class __attribute__((annotate(\""
|
||||
<< m_InFile << "\"))) "
|
||||
<< Declaration->getName() << ";\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
} // end namespace cling
|
@ -1,33 +0,0 @@
|
||||
#ifndef CLING_AUTOLOADING_VISITOR_H
|
||||
#define CLING_AUTOLOADING_VISITOR_H
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
|
||||
namespace cling {
|
||||
class NamespacePrinterRAII {
|
||||
public:
|
||||
NamespacePrinterRAII(std::string name) {
|
||||
llvm::outs()<< "namespace " <<name<<" {\n";
|
||||
}
|
||||
~NamespacePrinterRAII() {
|
||||
llvm::outs()<<"\n}\n";
|
||||
}
|
||||
};
|
||||
|
||||
class AutoloadingVisitor
|
||||
:public clang::RecursiveASTVisitor<AutoloadingVisitor> {
|
||||
public:
|
||||
AutoloadingVisitor(llvm::StringRef InFile,llvm::StringRef OutFile)
|
||||
:m_InFile(InFile),m_OutFile(OutFile){}
|
||||
bool VisitCXXRecordDecl(clang::CXXRecordDecl* Declaration);
|
||||
bool VisitFunctionDecl(clang::FunctionDecl* Declaration);
|
||||
bool VisitClassTemplateDecl(clang::ClassTemplateDecl* Declaration);
|
||||
|
||||
private:
|
||||
llvm::StringRef m_InFile;
|
||||
llvm::StringRef m_OutFile;
|
||||
};
|
||||
}//end namespace cling
|
||||
|
||||
#endif
|
@ -20,7 +20,6 @@ add_cling_library(clingInterpreter
|
||||
AutoSynthesizer.cpp
|
||||
AutoloadingTransform.cpp
|
||||
AutoloadCallback.cpp
|
||||
AutoloadingVisitor.cpp
|
||||
BackendPass.cpp
|
||||
CheckEmptyTransactionTransformer.cpp
|
||||
CIFactory.cpp
|
||||
@ -30,6 +29,7 @@ add_cling_library(clingInterpreter
|
||||
DynamicLibraryManager.cpp
|
||||
DynamicLookup.cpp
|
||||
DynamicExprInfo.cpp
|
||||
ForwardDeclPrinter.cpp
|
||||
IncrementalExecutor.cpp
|
||||
IncrementalParser.cpp
|
||||
Interpreter.cpp
|
||||
@ -49,6 +49,7 @@ add_cling_library(clingInterpreter
|
||||
|
||||
LINK_LIBS
|
||||
clangBasic
|
||||
clangAST
|
||||
)
|
||||
|
||||
if(NOT WIN32)
|
||||
|
847
lib/Interpreter/ForwardDeclPrinter.cpp
Normal file
847
lib/Interpreter/ForwardDeclPrinter.cpp
Normal file
@ -0,0 +1,847 @@
|
||||
#include "ForwardDeclPrinter.h"
|
||||
|
||||
namespace cling {
|
||||
using namespace clang;
|
||||
static QualType GetBaseType(QualType T) {
|
||||
// FIXME: This should be on the Type class!
|
||||
QualType BaseType = T;
|
||||
while (!BaseType->isSpecifierType()) {
|
||||
if (isa<TypedefType>(BaseType))
|
||||
break;
|
||||
else if (const PointerType* PTy = BaseType->getAs<PointerType>())
|
||||
BaseType = PTy->getPointeeType();
|
||||
else if (const BlockPointerType *BPy = BaseType->getAs<BlockPointerType>())
|
||||
BaseType = BPy->getPointeeType();
|
||||
else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType))
|
||||
BaseType = ATy->getElementType();
|
||||
else if (const FunctionType* FTy = BaseType->getAs<FunctionType>())
|
||||
BaseType = FTy->getReturnType();
|
||||
else if (const VectorType *VTy = BaseType->getAs<VectorType>())
|
||||
BaseType = VTy->getElementType();
|
||||
else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>())
|
||||
BaseType = RTy->getPointeeType();
|
||||
else
|
||||
llvm_unreachable("Unknown declarator!");
|
||||
}
|
||||
return BaseType;
|
||||
}
|
||||
static QualType getDeclType(Decl* D) {
|
||||
if (TypedefNameDecl* TDD = dyn_cast<TypedefNameDecl>(D))
|
||||
return TDD->getUnderlyingType();
|
||||
if (ValueDecl* VD = dyn_cast<ValueDecl>(D))
|
||||
return VD->getType();
|
||||
return QualType();
|
||||
}
|
||||
|
||||
raw_ostream& ForwardDeclPrinter::Indent(unsigned Indentation) {
|
||||
for (unsigned i = 0; i != Indentation; ++i)
|
||||
Out << " ";
|
||||
return Out;
|
||||
}
|
||||
void ForwardDeclPrinter::prettyPrintAttributes(Decl *D) {
|
||||
// if (Policy.PolishForDeclaration)
|
||||
// return;
|
||||
|
||||
// if (D->hasAttrs()) {
|
||||
// AttrVec &Attrs = D->getAttrs();
|
||||
// for (AttrVec::const_iterator i=Attrs.begin(), e=Attrs.end(); i!=e; ++i) {
|
||||
// Attr *A = *i;
|
||||
// A->printPretty(Out, Policy);
|
||||
// }
|
||||
// }
|
||||
Out << " __attribute__((annotate(\""
|
||||
<< m_SMgr.getFilename(D->getSourceRange().getBegin()) << "\"))) ";
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
|
||||
this->Indent();
|
||||
Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
|
||||
Out << ";\n";
|
||||
Decls.clear();
|
||||
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::Print(AccessSpecifier AS) {
|
||||
switch(AS) {
|
||||
case AS_none: llvm_unreachable("No access specifier!");
|
||||
case AS_public: Out << "public"; break;
|
||||
case AS_protected: Out << "protected"; break;
|
||||
case AS_private: Out << "private"; break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Common C declarations
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void ForwardDeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
|
||||
if (Policy.TerseOutput)
|
||||
return;
|
||||
if (Indent)
|
||||
Indentation += Policy.Indentation;
|
||||
|
||||
SmallVector<Decl*, 2> Decls;
|
||||
for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end();
|
||||
D != DEnd; ++D) {
|
||||
|
||||
// Don't print ObjCIvarDecls, as they are printed when visiting the
|
||||
// containing ObjCInterfaceDecl.
|
||||
if (isa<ObjCIvarDecl>(*D))
|
||||
continue;
|
||||
|
||||
// Skip over implicit declarations in pretty-printing mode.
|
||||
if (D->isImplicit())
|
||||
continue;
|
||||
|
||||
// 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<ElaboratedType>(BaseType))
|
||||
BaseType = cast<ElaboratedType>(BaseType)->getNamedType();
|
||||
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;
|
||||
}
|
||||
|
||||
if (isa<AccessSpecDecl>(*D)) {
|
||||
Indentation -= Policy.Indentation;
|
||||
this->Indent();
|
||||
Print(D->getAccess());
|
||||
Out << ":\n";
|
||||
Indentation += Policy.Indentation;
|
||||
continue;
|
||||
}
|
||||
|
||||
this->Indent();
|
||||
Visit(*D);
|
||||
|
||||
// FIXME: Need to be able to tell the FwdPrinter when
|
||||
const char *Terminator = 0;
|
||||
if (isa<OMPThreadPrivateDecl>(*D))
|
||||
Terminator = 0;
|
||||
else if (isa<FunctionDecl>(*D) &&
|
||||
cast<FunctionDecl>(*D)->isThisDeclarationADefinition())
|
||||
Terminator = 0;
|
||||
else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody())
|
||||
Terminator = 0;
|
||||
else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) ||
|
||||
isa<ObjCImplementationDecl>(*D) ||
|
||||
isa<ObjCInterfaceDecl>(*D) ||
|
||||
isa<ObjCProtocolDecl>(*D) ||
|
||||
isa<ObjCCategoryImplDecl>(*D) ||
|
||||
isa<ObjCCategoryDecl>(*D))
|
||||
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";
|
||||
}
|
||||
|
||||
if (!Decls.empty())
|
||||
ProcessDeclGroup(Decls);
|
||||
|
||||
if (Indent)
|
||||
Indentation -= Policy.Indentation;
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
|
||||
VisitDeclContext(D, false);
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
|
||||
if (!Policy.SuppressSpecifiers) {
|
||||
Out << "typedef ";
|
||||
|
||||
if (D->isModulePrivate())
|
||||
Out << "__module_private__ ";
|
||||
}
|
||||
D->getTypeSourceInfo()->getType().print(Out, Policy, D->getName());
|
||||
prettyPrintAttributes(D);
|
||||
// Indent() << ";\n";
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
|
||||
/*FIXME: Ugly Hack*/
|
||||
// if(!D->getLexicalDeclContext()->isNamespace()
|
||||
// && !D->getLexicalDeclContext()->isFileContext())
|
||||
// return;
|
||||
Out << "using " << *D;
|
||||
prettyPrintAttributes(D);
|
||||
Out << " = " << D->getTypeSourceInfo()->getType().getAsString(Policy);
|
||||
// Indent() << ";\n";
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitEnumDecl(EnumDecl *D) {
|
||||
if (D->getName().size() == 0)
|
||||
return;
|
||||
|
||||
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
|
||||
Out << "__module_private__ ";
|
||||
Out << "enum ";
|
||||
prettyPrintAttributes(D);
|
||||
if (D->isScoped()) {
|
||||
if (D->isScopedUsingClassTag())
|
||||
Out << "class ";
|
||||
else
|
||||
Out << "struct ";
|
||||
}
|
||||
Out << *D;
|
||||
|
||||
// if (D->isFixed())
|
||||
Out << " : " << D->getIntegerType().stream(Policy);
|
||||
|
||||
// if (D->isCompleteDefinition()) {
|
||||
// Out << " {\n";
|
||||
// VisitDeclContext(D);
|
||||
// Indent() << "};\n";
|
||||
// }
|
||||
|
||||
|
||||
Indent() << ";\n";
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitRecordDecl(RecordDecl *D) {
|
||||
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
|
||||
Out << "__module_private__ ";
|
||||
Out << D->getKindName();
|
||||
prettyPrintAttributes(D);
|
||||
if (D->getIdentifier())
|
||||
Out << ' ' << *D;
|
||||
|
||||
// if (D->isCompleteDefinition()) {
|
||||
// Out << " {\n";
|
||||
// VisitDeclContext(D);
|
||||
// Indent() << "}";
|
||||
// }
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
|
||||
Out << *D;
|
||||
if (Expr *Init = D->getInitExpr()) {
|
||||
Out << " = ";
|
||||
Init->printPretty(Out, 0, Policy, Indentation);
|
||||
}
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
if (D->getNameAsString().size() == 0 || D->getNameAsString()[0] == '_')
|
||||
return;
|
||||
if (D->getStorageClass() == SC_Static)
|
||||
return;
|
||||
/*FIXME:Ugly Hack: should idealy never be triggerred */
|
||||
if (D->isCXXClassMember()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
|
||||
CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
|
||||
/*FIXME:Ugly Hack*/
|
||||
// if (CDecl||ConversionDecl)
|
||||
// return;
|
||||
|
||||
if (!Policy.SuppressSpecifiers) {
|
||||
switch (D->getStorageClass()) {
|
||||
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: case SC_OpenCLWorkGroupLocal:
|
||||
llvm_unreachable("invalid for functions");
|
||||
}
|
||||
|
||||
if (D->isInlineSpecified()) Out << "inline ";
|
||||
if (D->isVirtualAsWritten()) Out << "virtual ";
|
||||
if (D->isModulePrivate()) Out << "__module_private__ ";
|
||||
if (D->isConstexpr() && !D->isExplicitlyDefaulted()) Out << "constexpr ";
|
||||
if ((CDecl && CDecl->isExplicitSpecified()) ||
|
||||
(ConversionDecl && ConversionDecl->isExplicit()))
|
||||
Out << "explicit ";
|
||||
}
|
||||
|
||||
PrintingPolicy SubPolicy(Policy);
|
||||
SubPolicy.SuppressSpecifiers = false;
|
||||
std::string Proto = D->getNameInfo().getAsString();
|
||||
QualType Ty = D->getType();
|
||||
while (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
|
||||
Proto = '(' + Proto + ')';
|
||||
Ty = PT->getInnerType();
|
||||
}
|
||||
|
||||
if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
|
||||
const FunctionProtoType *FT = 0;
|
||||
if (D->hasWrittenPrototype())
|
||||
FT = dyn_cast<FunctionProtoType>(AFT);
|
||||
|
||||
Proto += "(";
|
||||
if (FT) {
|
||||
llvm::raw_string_ostream POut(Proto);
|
||||
ForwardDeclPrinter ParamPrinter(POut, m_SMgr, SubPolicy, Indentation);
|
||||
for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
|
||||
if (i) POut << ", ";
|
||||
ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
|
||||
}
|
||||
|
||||
if (FT->isVariadic()) {
|
||||
if (D->getNumParams()) POut << ", ";
|
||||
POut << "...";
|
||||
}
|
||||
} else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) {
|
||||
for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
|
||||
if (i)
|
||||
Proto += ", ";
|
||||
Proto += D->getParamDecl(i)->getNameAsString();
|
||||
}
|
||||
}
|
||||
|
||||
Proto += ")";
|
||||
|
||||
if (FT) {
|
||||
if (FT->isConst())
|
||||
Proto += " const";
|
||||
if (FT->isVolatile())
|
||||
Proto += " volatile";
|
||||
if (FT->isRestrict())
|
||||
Proto += " __restrict";
|
||||
|
||||
switch (FT->getRefQualifier()) {
|
||||
case RQ_None:
|
||||
break;
|
||||
case RQ_LValue:
|
||||
Proto += " &";
|
||||
break;
|
||||
case RQ_RValue:
|
||||
Proto += " &&";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (FT && FT->hasDynamicExceptionSpec()) {
|
||||
Proto += " throw(";
|
||||
if (FT->getExceptionSpecType() == EST_MSAny)
|
||||
Proto += "...";
|
||||
else
|
||||
for (unsigned I = 0, N = FT->getNumExceptions(); I != N; ++I) {
|
||||
if (I)
|
||||
Proto += ", ";
|
||||
|
||||
Proto += FT->getExceptionType(I).getAsString(SubPolicy);
|
||||
}
|
||||
Proto += ")";
|
||||
} else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) {
|
||||
Proto += " noexcept";
|
||||
if (FT->getExceptionSpecType() == EST_ComputedNoexcept) {
|
||||
Proto += "(";
|
||||
llvm::raw_string_ostream EOut(Proto);
|
||||
FT->getNoexceptExpr()->printPretty(EOut, 0, SubPolicy,
|
||||
Indentation);
|
||||
EOut.flush();
|
||||
//Proto += EOut.str()
|
||||
//Commented out to fix swap bug, no idea why this was here
|
||||
//Print was already being called earlier above
|
||||
Proto += ")";
|
||||
}
|
||||
}
|
||||
|
||||
if (CDecl) {
|
||||
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();
|
||||
|
||||
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, 0, Policy, Indentation);
|
||||
else {
|
||||
for (unsigned I = 0; I != NumArgs; ++I) {
|
||||
if (isa<CXXDefaultArgExpr>(Args[I]))
|
||||
break;
|
||||
|
||||
if (I)
|
||||
Out << ", ";
|
||||
Args[I]->printPretty(Out, 0, Policy, Indentation);
|
||||
}
|
||||
}
|
||||
}
|
||||
Out << ")";
|
||||
if (BMInitializer->isPackExpansion())
|
||||
Out << "...";
|
||||
}
|
||||
} else if (!ConversionDecl && !isa<CXXDestructorDecl>(D)) {
|
||||
if (FT && FT->hasTrailingReturn()) {
|
||||
Out << "auto " << Proto << " -> ";
|
||||
Proto.clear();
|
||||
}
|
||||
AFT->getReturnType().print(Out, Policy, Proto);
|
||||
Proto.clear();
|
||||
}
|
||||
Out << Proto;
|
||||
} else {
|
||||
Ty.print(Out, Policy, Proto);
|
||||
}
|
||||
|
||||
prettyPrintAttributes(D);
|
||||
|
||||
if (D->isPure())
|
||||
Out << " = 0";
|
||||
else if (D->isDeletedAsWritten())
|
||||
Out << " = delete";
|
||||
else if (D->isExplicitlyDefaulted())
|
||||
Out << " = default";
|
||||
else if (D->doesThisDeclarationHaveABody() && !Policy.TerseOutput) {
|
||||
if (!D->hasPrototype() && D->getNumParams()) {
|
||||
// This is a K&R function definition, so we need to print the
|
||||
// parameters.
|
||||
Out << '\n';
|
||||
ForwardDeclPrinter ParamPrinter(Out,m_SMgr, SubPolicy, Indentation);
|
||||
Indentation += Policy.Indentation;
|
||||
for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
|
||||
Indent();
|
||||
ParamPrinter.VisitParmVarDecl(D->getParamDecl(i));
|
||||
Out << ";\n";
|
||||
}
|
||||
Indentation -= Policy.Indentation;
|
||||
} else
|
||||
Out << ' ';
|
||||
|
||||
// D->getBody()->printPretty(Out, 0, SubPolicy, Indentation);
|
||||
|
||||
}
|
||||
// Out << " __attribute__((annotate(\""
|
||||
// << m_SMgr.getFilename(D->getSourceRange().getBegin())<< "\"))) ";
|
||||
// Out <<";\n";
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitFriendDecl(FriendDecl *D) {
|
||||
// if (TypeSourceInfo *TSI = D->getFriendType()) {
|
||||
// unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists();
|
||||
// for (unsigned i = 0; i < NumTPLists; ++i)
|
||||
// PrintTemplateParameters(D->getFriendTypeTemplateParameterList(i));
|
||||
// Out << "friend ";
|
||||
// Out << " " << TSI->getType().getAsString(Policy);
|
||||
// }
|
||||
// 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 ";
|
||||
// VisitRedeclarableTemplateDecl(CTD);
|
||||
// }
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitFieldDecl(FieldDecl *D) {
|
||||
if (!Policy.SuppressSpecifiers && D->isMutable())
|
||||
Out << "mutable ";
|
||||
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
|
||||
Out << "__module_private__ ";
|
||||
Out << D->getASTContext().getUnqualifiedObjCPointerType(D->getType()).
|
||||
stream(Policy, D->getName());
|
||||
|
||||
if (D->isBitField()) {
|
||||
Out << " : ";
|
||||
D->getBitWidth()->printPretty(Out, 0, Policy, Indentation);
|
||||
}
|
||||
|
||||
Expr *Init = D->getInClassInitializer();
|
||||
if (!Policy.SuppressInitializers && Init) {
|
||||
if (D->getInClassInitStyle() == ICIS_ListInit)
|
||||
Out << " ";
|
||||
else
|
||||
Out << " = ";
|
||||
Init->printPretty(Out, 0, Policy, Indentation);
|
||||
}
|
||||
prettyPrintAttributes(D);
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitLabelDecl(LabelDecl *D) {
|
||||
Out << *D << ":";
|
||||
}
|
||||
|
||||
|
||||
void ForwardDeclPrinter::VisitVarDecl(VarDecl *D) {
|
||||
//FIXME:Ugly hack
|
||||
if(D->getStorageClass() == SC_Static) {
|
||||
return;
|
||||
}
|
||||
if(D->isDefinedOutsideFunctionOrMethod() && !(D->getStorageClass() == SC_Extern))
|
||||
Out << "extern ";
|
||||
|
||||
if (!Policy.SuppressSpecifiers) {
|
||||
StorageClass SC = D->getStorageClass();
|
||||
if (SC != SC_None)
|
||||
Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
|
||||
|
||||
switch (D->getTSCSpec()) {
|
||||
case TSCS_unspecified:
|
||||
break;
|
||||
case TSCS___thread:
|
||||
Out << "__thread ";
|
||||
break;
|
||||
case TSCS__Thread_local:
|
||||
Out << "_Thread_local ";
|
||||
break;
|
||||
case TSCS_thread_local:
|
||||
Out << "thread_local ";
|
||||
break;
|
||||
}
|
||||
|
||||
if (D->isModulePrivate())
|
||||
Out << "__module_private__ ";
|
||||
}
|
||||
|
||||
QualType T = D->getTypeSourceInfo()
|
||||
? D->getTypeSourceInfo()->getType()
|
||||
: D->getASTContext().getUnqualifiedObjCPointerType(D->getType());
|
||||
|
||||
//FIXME: It prints restrict as restrict
|
||||
//which is not valid C++
|
||||
//Should be __restrict
|
||||
//So, we ignore restrict here
|
||||
T.removeLocalRestrict();
|
||||
T.print(Out, Policy, D->getName());
|
||||
T.addRestrict();
|
||||
|
||||
Expr *Init = D->getInit();
|
||||
if (!Policy.SuppressInitializers && Init) {
|
||||
bool ImplicitInit = false;
|
||||
if (CXXConstructExpr *Construct =
|
||||
dyn_cast<CXXConstructExpr>(Init->IgnoreImplicit())) {
|
||||
if (D->getInitStyle() == VarDecl::CallInit &&
|
||||
!Construct->isListInitialization()) {
|
||||
ImplicitInit = Construct->getNumArgs() == 0 ||
|
||||
Construct->getArg(0)->isDefaultArgument();
|
||||
}
|
||||
}
|
||||
if (!ImplicitInit) {
|
||||
if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
|
||||
Out << "(";
|
||||
else if (D->getInitStyle() == VarDecl::CInit) {
|
||||
// Out << " = "; //FOR skipping default function args
|
||||
}
|
||||
// Init->printPretty(Out, 0, Policy, Indentation);//FOR skipping defalt function args
|
||||
if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
|
||||
Out << ")";
|
||||
}
|
||||
}
|
||||
if(D->isDefinedOutsideFunctionOrMethod())
|
||||
prettyPrintAttributes(D);
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
|
||||
VisitVarDecl(D);
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
|
||||
Out << "__asm (";
|
||||
D->getAsmString()->printPretty(Out, 0, Policy, Indentation);
|
||||
Out << ")";
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitImportDecl(ImportDecl *D) {
|
||||
Out << "@import " << D->getImportedModule()->getFullModuleName()
|
||||
<< ";\n";
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) {
|
||||
Out << "static_assert(";
|
||||
D->getAssertExpr()->printPretty(Out, 0, Policy, Indentation);
|
||||
Out << ", ";
|
||||
D->getMessage()->printPretty(Out, 0, Policy, Indentation);
|
||||
Out << ")";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// C++ declarations
|
||||
//----------------------------------------------------------------------------
|
||||
void ForwardDeclPrinter::VisitNamespaceDecl(NamespaceDecl *D) {
|
||||
if (D->isInline())
|
||||
Out << "inline ";
|
||||
Out << "namespace " << *D << " {\n";
|
||||
// VisitDeclContext(D);
|
||||
for(auto dit=D->decls_begin();dit!=D->decls_end();++dit) {
|
||||
this->Visit(*dit);
|
||||
Out << ";\n";
|
||||
}
|
||||
|
||||
Indent() << "}\n";
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
|
||||
Out << "using namespace ";
|
||||
if (D->getQualifier())
|
||||
D->getQualifier()->print(Out, Policy);
|
||||
Out << *D->getNominatedNamespaceAsWritten();
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
|
||||
Out << "namespace " << *D << " = ";
|
||||
if (D->getQualifier())
|
||||
D->getQualifier()->print(Out, Policy);
|
||||
Out << *D->getAliasedNamespace();
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitEmptyDecl(EmptyDecl *D) {
|
||||
// prettyPrintAttributes(D);
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
|
||||
|
||||
if(ClassDeclNames.find(D->getNameAsString()) != ClassDeclNames.end()
|
||||
/*|| D->getName().startswith("_")*/)
|
||||
return;
|
||||
|
||||
if (D->getNameAsString().size() == 0)
|
||||
return;
|
||||
|
||||
if (!Policy.SuppressSpecifiers && D->isModulePrivate())
|
||||
Out << "__module_private__ ";
|
||||
Out << D->getKindName();
|
||||
Out << " __attribute__((annotate(\""
|
||||
<< m_SMgr.getFilename(D->getSourceRange().getBegin()) << "\"))) ";
|
||||
if (D->getIdentifier())
|
||||
Out << ' ' << *D ;
|
||||
|
||||
// if (D->isCompleteDefinition()) {
|
||||
// // Print the base classes
|
||||
// if (D->getNumBases()) {
|
||||
// Out << " : ";
|
||||
// for (CXXRecordDecl::base_class_iterator Base = D->bases_begin(),
|
||||
// BaseEnd = D->bases_end(); Base != BaseEnd; ++Base) {
|
||||
// if (Base != D->bases_begin())
|
||||
// Out << ", ";
|
||||
|
||||
// if (Base->isVirtual())
|
||||
// Out << "virtual ";
|
||||
|
||||
// AccessSpecifier AS = Base->getAccessSpecifierAsWritten();
|
||||
// if (AS != AS_none)
|
||||
// Print(AS);
|
||||
// Out << " " << Base->getType().getAsString(Policy);
|
||||
|
||||
// if (Base->isPackExpansion())
|
||||
// Out << "...";
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Print the class definition
|
||||
// // FIXME: Doesn't print access specifiers, e.g., "public:"
|
||||
// Out << " {\n";
|
||||
// VisitDeclContext(D);
|
||||
// Indent() << "}";
|
||||
// }
|
||||
// Out << ";\n";
|
||||
ClassDeclNames.insert(D->getNameAsString());
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::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
|
||||
Visit(*D->decls_begin());
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params,
|
||||
const TemplateArgumentList *Args) {
|
||||
assert(Params);
|
||||
assert(!Args || Params->size() == Args->size());
|
||||
|
||||
Out << "template <";
|
||||
|
||||
for (unsigned i = 0, e = Params->size(); i != e; ++i) {
|
||||
if (i != 0)
|
||||
Out << ", ";
|
||||
|
||||
const Decl *Param = Params->getParam(i);
|
||||
if (const TemplateTypeParmDecl *TTP =
|
||||
dyn_cast<TemplateTypeParmDecl>(Param)) {
|
||||
|
||||
if (TTP->wasDeclaredWithTypename())
|
||||
Out << "typename ";
|
||||
else
|
||||
Out << "class ";
|
||||
|
||||
if (TTP->isParameterPack())
|
||||
Out << "... ";
|
||||
|
||||
Out << *TTP;
|
||||
|
||||
if (Args) {
|
||||
Out << " = ";
|
||||
Args->get(i).print(Policy, Out);
|
||||
} else if (TTP->hasDefaultArgument()) {
|
||||
// Out << " = ";
|
||||
// Out << TTP->getDefaultArgument().getAsString(Policy);
|
||||
};
|
||||
} else if (const NonTypeTemplateParmDecl *NTTP =
|
||||
dyn_cast<NonTypeTemplateParmDecl>(Param)) {
|
||||
Out << NTTP->getType().getAsString(Policy);
|
||||
if (NTTP->isParameterPack() && !isa<PackExpansionType>(NTTP->getType()))
|
||||
Out << "...";
|
||||
|
||||
if (IdentifierInfo *Name = NTTP->getIdentifier()) {
|
||||
Out << ' ';
|
||||
Out << Name->getName();
|
||||
}
|
||||
|
||||
if (Args) {
|
||||
Out << " = ";
|
||||
Args->get(i).print(Policy, Out);
|
||||
} else if (NTTP->hasDefaultArgument()) {
|
||||
// Out << " = ";
|
||||
// NTTP->getDefaultArgument()->printPretty(Out, 0, Policy, Indentation);
|
||||
}
|
||||
} else if (const TemplateTemplateParmDecl *TTPD =
|
||||
dyn_cast<TemplateTemplateParmDecl>(Param)) {
|
||||
VisitTemplateDecl(TTPD);
|
||||
// FIXME: print the default argument, if present.
|
||||
}
|
||||
}
|
||||
|
||||
Out << "> ";
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
|
||||
PrintTemplateParameters(D->getTemplateParameters());
|
||||
|
||||
if (const TemplateTemplateParmDecl *TTP =
|
||||
dyn_cast<TemplateTemplateParmDecl>(D)) {
|
||||
Out << "class ";
|
||||
if (TTP->isParameterPack())
|
||||
Out << "...";
|
||||
Out << D->getName();
|
||||
} else {
|
||||
Visit(D->getTemplatedDecl());
|
||||
}
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
||||
if(D->getNameAsString().size() == 0 || D->getNameAsString()[0] == '_')
|
||||
return;
|
||||
// if (D->getStorageClass() == SC_Static)
|
||||
// return;
|
||||
/*FIXME:Ugly Hack: should idealy never be triggerred */
|
||||
if (D->isCXXClassMember())
|
||||
return;
|
||||
|
||||
if (PrintInstantiation) {
|
||||
TemplateParameterList *Params = D->getTemplateParameters();
|
||||
for (FunctionTemplateDecl::spec_iterator I = D->spec_begin(),
|
||||
E = D->spec_end(); I != E; ++I) {
|
||||
PrintTemplateParameters(Params, (*I)->getTemplateSpecializationArgs());
|
||||
Visit(*I);
|
||||
}
|
||||
}
|
||||
|
||||
return VisitRedeclarableTemplateDecl(D);
|
||||
}
|
||||
|
||||
void ForwardDeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
||||
if(ClassDeclNames.find(D->getNameAsString()) != ClassDeclNames.end()
|
||||
|| D->getName().size() == 0 )
|
||||
return;
|
||||
if (PrintInstantiation) {
|
||||
TemplateParameterList *Params = D->getTemplateParameters();
|
||||
for (ClassTemplateDecl::spec_iterator I = D->spec_begin(),
|
||||
E = D->spec_end(); I != E; ++I) {
|
||||
PrintTemplateParameters(Params, &(*I)->getTemplateArgs());
|
||||
Visit(*I);
|
||||
Out << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
return VisitRedeclarableTemplateDecl(D);
|
||||
}
|
||||
void ForwardDeclPrinter::VisitClassTemplateSpecializationDecl
|
||||
(clang::ClassTemplateSpecializationDecl* D) {
|
||||
|
||||
//D->dump();
|
||||
|
||||
}
|
||||
}//end namespace cling
|
76
lib/Interpreter/ForwardDeclPrinter.h
Normal file
76
lib/Interpreter/ForwardDeclPrinter.h
Normal file
@ -0,0 +1,76 @@
|
||||
//TODO: Adapted from DeclPrinter, may need to be rewritten
|
||||
#ifndef CLING_AUTOLOADING_VISITOR_H
|
||||
#define CLING_AUTOLOADING_VISITOR_H
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/DeclVisitor.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/PrettyPrinter.h"
|
||||
#include "clang/Basic/Module.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
namespace cling {
|
||||
|
||||
class ForwardDeclPrinter : public clang::DeclVisitor<ForwardDeclPrinter> {
|
||||
llvm::raw_ostream &Out;
|
||||
clang::PrintingPolicy Policy;
|
||||
unsigned Indentation;
|
||||
bool PrintInstantiation;
|
||||
|
||||
llvm::raw_ostream& Indent() { return Indent(Indentation); }
|
||||
llvm::raw_ostream& Indent(unsigned Indentation);
|
||||
void ProcessDeclGroup(llvm::SmallVectorImpl<clang::Decl*>& Decls);
|
||||
|
||||
void Print(clang::AccessSpecifier AS);
|
||||
|
||||
std::set<std::string> ClassDeclNames;
|
||||
clang::SourceManager& m_SMgr;
|
||||
|
||||
public:
|
||||
ForwardDeclPrinter(llvm::raw_ostream &Out, clang::SourceManager& smgr,
|
||||
const clang::PrintingPolicy &Policy =clang::PrintingPolicy(clang::LangOptions()),
|
||||
unsigned Indentation = 0, bool PrintInstantiation = false)
|
||||
: Out(Out), Policy(Policy), Indentation(Indentation),
|
||||
PrintInstantiation(PrintInstantiation),m_SMgr(smgr)
|
||||
{ }
|
||||
|
||||
void VisitDeclContext(clang::DeclContext *DC, bool Indent = true);
|
||||
|
||||
void VisitTranslationUnitDecl(clang::TranslationUnitDecl *D);
|
||||
void VisitTypedefDecl(clang::TypedefDecl *D);
|
||||
void VisitTypeAliasDecl(clang::TypeAliasDecl *D);
|
||||
void VisitEnumDecl(clang::EnumDecl *D);
|
||||
void VisitRecordDecl(clang::RecordDecl *D);
|
||||
void VisitEnumConstantDecl(clang::EnumConstantDecl *D);
|
||||
void VisitEmptyDecl(clang::EmptyDecl *D);
|
||||
void VisitFunctionDecl(clang::FunctionDecl *D);
|
||||
void VisitFriendDecl(clang::FriendDecl *D);
|
||||
void VisitFieldDecl(clang::FieldDecl *D);
|
||||
void VisitVarDecl(clang::VarDecl *D);
|
||||
void VisitLabelDecl(clang::LabelDecl *D);
|
||||
void VisitParmVarDecl(clang::ParmVarDecl *D);
|
||||
void VisitFileScopeAsmDecl(clang::FileScopeAsmDecl *D);
|
||||
void VisitImportDecl(clang::ImportDecl *D);
|
||||
void VisitStaticAssertDecl(clang::StaticAssertDecl *D);
|
||||
void VisitNamespaceDecl(clang::NamespaceDecl *D);
|
||||
void VisitUsingDirectiveDecl(clang::UsingDirectiveDecl *D);
|
||||
void VisitNamespaceAliasDecl(clang::NamespaceAliasDecl *D);
|
||||
void VisitCXXRecordDecl(clang::CXXRecordDecl *D);
|
||||
void VisitLinkageSpecDecl(clang::LinkageSpecDecl *D);
|
||||
void VisitTemplateDecl(const clang::TemplateDecl *D);
|
||||
void VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *D);
|
||||
void VisitClassTemplateDecl(clang::ClassTemplateDecl *D);
|
||||
void VisitClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl* D);
|
||||
|
||||
void PrintTemplateParameters(const clang::TemplateParameterList *Params,
|
||||
const clang::TemplateArgumentList *Args = 0);
|
||||
void prettyPrintAttributes(clang::Decl *D);
|
||||
};
|
||||
}
|
||||
#endif
|
@ -13,7 +13,7 @@
|
||||
#include "DynamicLookup.h"
|
||||
#include "IncrementalExecutor.h"
|
||||
#include "IncrementalParser.h"
|
||||
#include "AutoloadingVisitor.h"
|
||||
#include "ForwardDeclPrinter.h"
|
||||
|
||||
#include "cling/Interpreter/CIFactory.h"
|
||||
#include "cling/Interpreter/ClangInternalState.h"
|
||||
@ -1190,19 +1190,65 @@ namespace cling {
|
||||
|
||||
void Interpreter::GenerateAutoloadingMap(llvm::StringRef inFile,
|
||||
llvm::StringRef outFile) {
|
||||
cling::Transaction* T;
|
||||
this->declare(std::string("#include \"") + std::string(inFile) + "\"", &T);
|
||||
for(auto dcit=T->decls_begin(); dcit!=T->decls_end(); ++dcit) {
|
||||
// cling::Transaction* T = 0;
|
||||
|
||||
// CompilationResult result = this->declare(std::string("#include \"")
|
||||
// + std::string(inFile) + "\"", &T);
|
||||
llvm::SmallVector<std::string,30> incpaths;
|
||||
GetIncludePaths(incpaths,true,false);
|
||||
|
||||
CompilationOptions CO;
|
||||
CO.DeclarationExtraction = 0;
|
||||
CO.ValuePrinting = 0;
|
||||
CO.ResultEvaluation = 0;
|
||||
CO.DynamicScoping = 0;
|
||||
CO.Debug = isPrintingDebug();
|
||||
|
||||
cling::Transaction* T = m_IncrParser->Parse
|
||||
(std::string("#include \"") + std::string(inFile) + "\"", CO);
|
||||
|
||||
// if (result != CompilationResult::kSuccess) {
|
||||
// llvm::outs() << "Compilation failure\n";
|
||||
// return;
|
||||
// }
|
||||
std::string err;
|
||||
llvm::raw_fd_ostream out(outFile.data(), err,
|
||||
llvm::sys::fs::OpenFlags::F_None);
|
||||
|
||||
ForwardDeclPrinter visitor(out,getSema().getSourceManager());
|
||||
|
||||
for(auto dcit = T->decls_begin(); dcit != T->decls_end(); ++dcit) {
|
||||
Transaction::DelayCallInfo& dci = *dcit;
|
||||
|
||||
for(auto dit = dci.m_DGR.begin(); dit != dci.m_DGR.end(); ++dit) {
|
||||
clang::Decl* decl = *dit;
|
||||
auto visitor = new AutoloadingVisitor(inFile,outFile);
|
||||
visitor->TraverseDecl(decl);
|
||||
delete visitor;
|
||||
if(dci.m_DGR.isNull()) {
|
||||
break;
|
||||
}
|
||||
if (dci.m_Call == Transaction::kCCIHandleTopLevelDecl) {
|
||||
for(auto dit = dci.m_DGR.begin(); dit != dci.m_DGR.end(); ++dit) {
|
||||
clang::Decl* decl = *dit;
|
||||
|
||||
//skip logic start
|
||||
bool skip = false;
|
||||
auto filename = getSema().getSourceManager().getFilename
|
||||
(decl->getSourceRange().getBegin());
|
||||
auto path = llvm::sys::path::parent_path(filename);
|
||||
for (auto p : incpaths) {
|
||||
if (llvm::sys::fs::equivalent(p,path)
|
||||
|| llvm::sys::fs::equivalent
|
||||
(p,llvm::sys::path::parent_path(path))) {
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (skip)
|
||||
continue;
|
||||
//skip logic end
|
||||
|
||||
visitor.Visit(decl);
|
||||
out << ";\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
T->setState(Transaction::kCommitted);
|
||||
return;
|
||||
}
|
||||
} // namespace cling
|
||||
} //end namespace cling
|
||||
|
27
test/Autoloading/AutoForwarding.C
Normal file
27
test/Autoloading/AutoForwarding.C
Normal file
@ -0,0 +1,27 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// CLING - the C++ LLVM-based InterpreterG :)
|
||||
//
|
||||
// This file is dual-licensed: you can choose to license it under the University
|
||||
// of Illinois Open Source License or the GNU Lesser General Public License. See
|
||||
// LICENSE.TXT for details.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// RUN: cat %s | %cling -I %S -Xclang -verify
|
||||
// Test FwdPrinterTest
|
||||
|
||||
|
||||
#include "cling/Interpreter/Interpreter.h"
|
||||
// #include "cling/Interpreter/AutoloadCallback.h"
|
||||
gCling->GenerateAutoloadingMap("Def2.h","test.h");
|
||||
|
||||
gCling->process("const char * const argV = \"cling\";");
|
||||
gCling->process("cling::Interpreter *DefaultInterp;");
|
||||
|
||||
gCling->process("DefaultInterp = new cling::Interpreter(1, &argV);");
|
||||
// gCling->process("DefaultInterp->setCallbacks(new cling::AutoloadCallback(DefaultInterp));")
|
||||
gCling->process("DefaultInterp->process(\"#include \\\"test.h\\\"\");");
|
||||
gCling->process("DefaultInterp->process(\"#include \\\"Def2.h\\\"\");");
|
||||
|
||||
//expected-no-diagnostics
|
||||
|
||||
.q
|
32
test/Autoloading/Def2.h
Normal file
32
test/Autoloading/Def2.h
Normal file
@ -0,0 +1,32 @@
|
||||
namespace M {
|
||||
namespace N {
|
||||
template<typename T>
|
||||
T function(T t) {
|
||||
return t;
|
||||
}
|
||||
class A{};
|
||||
template<typename T>class B : public A {};
|
||||
class C :public B<int> {};
|
||||
|
||||
}
|
||||
}
|
||||
namespace stdtest {
|
||||
class istream{};
|
||||
extern istream cin;
|
||||
|
||||
template<typename T,typename A> class vector{};
|
||||
template<typename... T>class tuple{};
|
||||
|
||||
template<bool B, class T, class F>
|
||||
struct conditional { typedef T type; };
|
||||
|
||||
template<class T, class F>
|
||||
struct conditional<false, T, F> { typedef F type; };
|
||||
|
||||
template<bool B, class T = void>
|
||||
struct enable_if {};
|
||||
|
||||
template<class T>
|
||||
struct enable_if<true, T> { typedef T type; };
|
||||
|
||||
}
|
@ -8,8 +8,6 @@
|
||||
|
||||
// RUN: cat %s | %cling 2>&1 -I %S -Xclang -verify
|
||||
// Test enumTest
|
||||
#include "cling/Interpreter/AutoloadCallback.h"
|
||||
gCling->setCallbacks(new cling::AutoloadCallback(gCling));
|
||||
|
||||
.rawInput 1
|
||||
enum __attribute__((annotate("Enum.h"))) class EC;
|
||||
|
24
test/Autoloading/Fail.C
Normal file
24
test/Autoloading/Fail.C
Normal file
@ -0,0 +1,24 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// CLING - the C++ LLVM-based InterpreterG :)
|
||||
//
|
||||
// This file is dual-licensed: you can choose to license it under the University
|
||||
// of Illinois Open Source License or the GNU Lesser General Public License. See
|
||||
// LICENSE.TXT for details.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// RUN: cat %s | %cling -I %S -Xclang -verify
|
||||
// Test templateFail
|
||||
//XFAIL: *
|
||||
//All the currently failing stuff
|
||||
|
||||
#include "cling/Interpreter/Interpreter.h"
|
||||
// #include "cling/Interpreter/AutoloadCallback.h"
|
||||
gCling->GenerateAutoloadingMap("Fail.h","test.h");
|
||||
|
||||
gCling->process("const char * const argV = \"cling\";");
|
||||
gCling->process("cling::Interpreter *DefaultInterp;");
|
||||
|
||||
gCling->process("DefaultInterp = new cling::Interpreter(1, &argV);");
|
||||
gCling->process("DefaultInterp->process(\"#include \\\"test.h\\\"\");");
|
||||
|
||||
.q
|
38
test/Autoloading/Fail.h
Normal file
38
test/Autoloading/Fail.h
Normal file
@ -0,0 +1,38 @@
|
||||
namespace test { //implicit instantiation
|
||||
template<bool B, class T, class F>
|
||||
struct conditional { typedef T type; };
|
||||
|
||||
template<class T, class F>
|
||||
struct conditional<false, T, F> { typedef F type; };
|
||||
|
||||
template <typename _Tp> using example = typename conditional<true,int,float>::type;
|
||||
}//end namespace test
|
||||
|
||||
namespace test { //nested name specifier
|
||||
class HasSubType {
|
||||
public:
|
||||
class SubType {};
|
||||
};
|
||||
HasSubType::SubType FunctionUsingSubtype(HasSubType::SubType s){return s;}
|
||||
extern HasSubType::SubType variable;//locale::id id
|
||||
|
||||
}//end namespace test
|
||||
|
||||
namespace test { //restrict keyword: try include/mmprivate.h and strlcpy.h when fixed
|
||||
typedef long ssize_t;
|
||||
typedef unsigned int size_t;
|
||||
//Has signature of readlink from unistd.h
|
||||
extern ssize_t FunctionUsingRestrictPtr (const char *__restrict __path,
|
||||
char *__restrict __buf, size_t __len);
|
||||
}//end namespace test
|
||||
|
||||
namespace test { //default template arg
|
||||
template <typename T,int MAX=100> class Stack {
|
||||
};
|
||||
Stack<int> FunctionReturningStack(){return Stack<int>();}
|
||||
}//end namespace test
|
||||
|
||||
namespace test {
|
||||
//#include<tuple> //'tie' function
|
||||
//commented out to skip huge output
|
||||
}
|
@ -9,9 +9,6 @@
|
||||
// RUN: cat %s | %cling -I %S -Xclang -verify
|
||||
// Test forwardDeclaration
|
||||
|
||||
#include "cling/Interpreter/AutoloadCallback.h"
|
||||
gCling->setCallbacks(new cling::AutoloadCallback(gCling));
|
||||
|
||||
.rawInput 1
|
||||
int id(int) __attribute__((annotate("Def.h")));
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
// RUN: cat %s | %cling -I %S -Xclang -verify
|
||||
// Test incompleteType
|
||||
//XFAIL: *
|
||||
//Becasue functionality is disabled now
|
||||
|
||||
#include "cling/Interpreter/AutoloadCallback.h"
|
||||
gCling->setCallbacks(new cling::AutoloadCallback(gCling));
|
||||
|
@ -9,7 +9,7 @@
|
||||
// RUN: cat %s | %cling -I %S -Xclang -verify
|
||||
// Test stlFwd
|
||||
//XFAIL: *
|
||||
//fail because the way the autoloading transformation is loaded now, causes assertion failure for this
|
||||
// Only for reference purposes, doesn't actually use FwdPrinter
|
||||
namespace std {
|
||||
|
||||
template <typename T,typename A> class __attribute__((annotate("vector"))) vector;
|
||||
@ -32,4 +32,8 @@ namespace std {
|
||||
#include<type_traits>
|
||||
#include<map>
|
||||
#include<algorithm>
|
||||
#include<string>
|
||||
#include<string>
|
||||
|
||||
//expected-no-diagnostics
|
||||
.q
|
||||
|
||||
|
22
test/Autoloading/test.h
Normal file
22
test/Autoloading/test.h
Normal file
@ -0,0 +1,22 @@
|
||||
namespace test {
|
||||
template <bool B, class T, class F> struct __attribute__((annotate("./Fail.h"))) conditional;
|
||||
;
|
||||
template <typename _Tp> using example __attribute__((annotate("./Fail.h"))) = typename conditional<true, int, float>::type;
|
||||
}
|
||||
;
|
||||
namespace test {
|
||||
class __attribute__((annotate("./Fail.h"))) HasSubType;
|
||||
class HasSubType::SubType FunctionUsingSubtype(class HasSubType::SubType s) __attribute__((annotate("./Fail.h"))) ;
|
||||
}
|
||||
;
|
||||
namespace test {
|
||||
typedef long ssize_t __attribute__((annotate("./Fail.h"))) ;
|
||||
typedef unsigned int size_t __attribute__((annotate("./Fail.h"))) ;
|
||||
extern ssize_t FunctionUsingRestrictPtr(const char *restrict __path, char *restrict __buf, size_t __len) __attribute__((annotate("./Fail.h"))) ;
|
||||
}
|
||||
;
|
||||
namespace test {
|
||||
template <typename T, int MAX> class __attribute__((annotate("./Fail.h"))) Stack;
|
||||
Stack<int> FunctionReturningStack() __attribute__((annotate("./Fail.h"))) ;
|
||||
}
|
||||
;
|
Loading…
Reference in New Issue
Block a user