Unload fwd decls of enums; redeclaring definitions fails.

This commit is contained in:
Axel Naumann 2015-06-19 16:26:08 +02:00 committed by sftnight
parent 4834289abd
commit 1718483b7e
3 changed files with 22 additions and 36 deletions

View File

@ -23,6 +23,7 @@
#include "cling/Interpreter/InterpreterCallbacks.h"
#include "cling/Interpreter/AutoloadCallback.h"
#include "cling/Interpreter/Transaction.h"
#include "TransactionUnloader.h"
namespace {
static const char annoTag[] = "$clingAutoload$";
@ -67,6 +68,7 @@ namespace cling {
bool m_IsStoringState;
AutoloadCallback::FwdDeclsMap* m_Map;
clang::Preprocessor* m_PP;
clang::Sema* m_Sema;
const clang::FileEntry* m_PrevFE;
std::string m_PrevFileName;
private:
@ -108,9 +110,10 @@ namespace cling {
public:
AutoloadingVisitor():
m_IsStoringState(false), m_Map(0), m_PP(0), m_PrevFE(0) {}
void RemoveDefaultArgsOf(Decl* D) {
m_IsStoringState(false), m_Map(0), m_PP(0), m_Sema(0), m_PrevFE(0) {}
void RemoveDefaultArgsOf(Decl* D, Sema* S) {
//D = D->getMostRecentDecl();
m_Sema = S;
TraverseDecl(D);
//while ((D = D->getPreviousDecl()))
// TraverseDecl(D);
@ -136,35 +139,8 @@ namespace cling {
if (!D->hasAttr<AnnotateAttr>())
return true;
AnnotateAttr* attr = D->getAttr<AnnotateAttr>();
if (!attr)
return true;
switch (D->getKind()) {
default:
if (AnnotateAttr* attr = D->getAttr<AnnotateAttr>())
InsertIntoAutoloadingState(D, attr->getAnnotation());
break;
case Decl::Enum:
// EnumDecls have extra information 2 chars after the filename used
// for extra fixups.
EnumDecl* ED = cast<EnumDecl>(D);
if (ED->isFixed()) {
StringRef str = ED->getAttr<AnnotateAttr>()->getAnnotation();
char ch = str.back();
// str.drop_back(2);
ED->getAttr<AnnotateAttr>()->setAnnotation(ED->getASTContext(), str);
struct EnumDeclDerived: public EnumDecl {
static void setFixed(EnumDecl* ED, bool value = true) {
((EnumDeclDerived*)ED)->IsFixed = value;
}
};
if (ch != '1')
EnumDeclDerived::setFixed(ED, false);
}
InsertIntoAutoloadingState(D, attr->getAnnotation().drop_back(2));
break;
}
return true;
}
@ -245,6 +221,18 @@ namespace cling {
D->setDefaultArg(nullptr);
return true;
}
bool VisitEnumDecl(EnumDecl* D) {
VisitDecl(D);
if (m_IsStoringState)
return true;
// Now that we will read the full enum, unload the forward decl.
TransactionUnloader Unloader(m_Sema, 0);
Unloader.UnloadDecl(D);
return true;
}
};
void AutoloadCallback::InclusionDirective(clang::SourceLocation HashLoc,
@ -266,7 +254,7 @@ namespace cling {
AutoloadingVisitor defaultArgsCleaner;
for (auto D : found->second) {
defaultArgsCleaner.RemoveDefaultArgsOf(D);
defaultArgsCleaner.RemoveDefaultArgsOf(D, &getInterpreter()->getSema());
}
// Don't need to keep track of cleaned up decls from file.
m_Map.erase(found);

View File

@ -150,7 +150,7 @@ namespace cling {
return Out();
}
void ForwardDeclPrinter::prettyPrintAttributes(Decl *D, std::string extra) {
void ForwardDeclPrinter::prettyPrintAttributes(Decl *D) {
if (D->getSourceRange().isInvalid())
return;
@ -195,8 +195,6 @@ namespace cling {
// assert ( file.length() != 0 && "Filename Should not be blank");
Out() << " __attribute__((annotate(\"$clingAutoload$"
<< llvm::StringRef(includeText, includeEnd - includeText);
if (!extra.empty())
Out() << " " << extra;
Out() << "\"))) ";
}
@ -260,7 +258,7 @@ namespace cling {
if (!m_Policy.SuppressSpecifiers && D->isModulePrivate())
Out() << "__module_private__ ";
Out() << "enum ";
prettyPrintAttributes(D,std::to_string(D->isFixed()));
prettyPrintAttributes(D);
if (D->isScoped()) {
if (D->isScopedUsingClassTag())
Out() << "class ";

View File

@ -155,7 +155,7 @@ namespace cling {
void PrintTemplateParameters(llvm::raw_ostream& Stream,
clang::TemplateParameterList *Params,
const clang::TemplateArgumentList *Args = 0);
void prettyPrintAttributes(clang::Decl *D, std::string extra = "");
void prettyPrintAttributes(clang::Decl *D);
bool isOperator(clang::FunctionDecl* D);
bool hasDefaultArgument(clang::FunctionDecl* D);