RecordDecls are special. They have implicitly injected class names.

struct C {
   // C is implicitly declared here as a synonym for the class name.
};

C::C c; // same as "C c;"

In this example clang will inject another declaration to provide the name C
within the record decl. For unknown reason it is added to the redecl chain.
When we revert a class decl we must make sure that the implicitly injected name
in the chain is gone.
This commit is contained in:
Vassil Vassilev 2014-02-08 14:57:37 +01:00 committed by sftnight
parent 8b4b340f6e
commit fa9fe845cd

View File

@ -165,6 +165,14 @@ namespace cling {
///
bool VisitTagDecl(TagDecl* TD);
///\brief Removes a RecordDecl. We shouldn't remove the implicit class
/// declaration.
///\param[in] RD - The declaration to be removed.
///
///\returns true on success.
///
bool VisitRecordDecl(RecordDecl* RD);
///\brief Remove the macro from the Preprocessor.
/// @param[in] MD - The MacroDirectiveInfo containing the IdentifierInfo and
/// MacroDirective to forward.
@ -608,6 +616,31 @@ namespace cling {
return Successful;
}
bool DeclReverter::VisitRecordDecl(RecordDecl* RD) {
if (RD->isInjectedClassName())
return true;
/// The injected class name in C++ is the name of the class that
/// appears inside the class itself. For example:
///
/// \code
/// struct C {
/// // C is implicitly declared here as a synonym for the class name.
/// };
///
/// C::C c; // same as "C c;"
/// \endcode
// It is another question why it is on the redecl chain.
RecordDecl* PrevRD = RD->getPreviousDecl();
bool Successful = VisitTagDecl(RD);
if (PrevRD) {
assert(PrevRD->isInjectedClassName() && "Not injected classname?");
Successful &= VisitTagDecl(PrevRD);
}
return Successful;
}
void DeclReverter::MaybeRemoveDeclFromModule(GlobalDecl& GD) const {
if (!m_CurTransaction->getModule()) // syntax-only mode exit
return;