void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { if (Policy.TerseOutput) return; if (Indent) Indentation += Policy.Indentation; SmallVector<Decl*, 2> Decls; bool MergeOneDecl = false; 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; // Don't print implicit specializations, as they are printed when visiting // corresponding templates. if (auto FD = dyn_cast<FunctionDecl>(*D)) if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation && !isa<ClassTemplateSpecializationDecl>(DC)) continue; // 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() && (!MergeOneDecl || Decls.size() == 1)) { 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); MergeOneDecl = false; continue; } // Attempt to merge named tags too, but // only with a single decl. (This cleans // up warnings about unused declarations // when a struct is defined inline inside // another struct.) Only merge one variable // declaration, so we don't have to worry // about whether the storage class and/or // qualifiers match. if (isa<TagDecl>(*D)) { Decls.push_back(*D); MergeOneDecl = true; 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 DeclPrinter when const char *Terminator = nullptr; if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D) || isa<PragmaPupcDecl>(*D)) Terminator = nullptr; else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody()) Terminator = nullptr; else if (auto FD = dyn_cast<FunctionDecl>(*D)) { if (FD->isThisDeclarationADefinition()) Terminator = nullptr; else Terminator = ";"; } else if (auto TD = dyn_cast<FunctionTemplateDecl>(*D)) { if (TD->getTemplatedDecl()->isThisDeclarationADefinition()) Terminator = nullptr; else Terminator = ";"; } else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) || isa<ObjCImplementationDecl>(*D) || isa<ObjCInterfaceDecl>(*D) || isa<ObjCProtocolDecl>(*D) || isa<ObjCCategoryImplDecl>(*D) || isa<ObjCCategoryDecl>(*D)) Terminator = nullptr; else if (isa<EnumConstantDecl>(*D)) { DeclContext::decl_iterator Next = D; ++Next; if (Next != DEnd) Terminator = ","; } else Terminator = ";"; if (Terminator) Out << Terminator; if (!Policy.TerseOutput && ((isa<FunctionDecl>(*D) && cast<FunctionDecl>(*D)->doesThisDeclarationHaveABody()) || (isa<FunctionTemplateDecl>(*D) && cast<FunctionTemplateDecl>(*D)->getTemplatedDecl()->doesThisDeclarationHaveABody()))) ; // StmtPrinter already added '\n' after CompoundStmt. else Out << "\n"; // Declare target attribute is special one, natural spelling for the pragma // assumes "ending" construct so print it here. if (D->hasAttr<OMPDeclareTargetDeclAttr>()) Out << "#pragma omp end declare target\n"; } if (!Decls.empty()) ProcessDeclGroup(Decls); if (Indent) Indentation -= Policy.Indentation; }
void DeclPrinter::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 DeclPrinter when const char *Terminator = nullptr; if (isa<OMPThreadPrivateDecl>(*D) || isa<OMPDeclareReductionDecl>(*D)) Terminator = nullptr; else if (isa<FunctionDecl>(*D) && cast<FunctionDecl>(*D)->isThisDeclarationADefinition()) Terminator = nullptr; else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->getBody()) Terminator = nullptr; else if (isa<NamespaceDecl>(*D) || isa<LinkageSpecDecl>(*D) || isa<ObjCImplementationDecl>(*D) || isa<ObjCInterfaceDecl>(*D) || isa<ObjCProtocolDecl>(*D) || isa<ObjCCategoryImplDecl>(*D) || isa<ObjCCategoryDecl>(*D)) Terminator = nullptr; else if (isa<EnumConstantDecl>(*D)) { DeclContext::decl_iterator Next = D; ++Next; if (Next != DEnd) Terminator = ","; } else Terminator = ";"; if (Terminator) Out << Terminator; Out << "\n"; // Declare target attribute is special one, natural spelling for the pragma // assumes "ending" construct so print it here. if (D->hasAttr<OMPDeclareTargetDeclAttr>()) Out << "#pragma omp end declare target\n"; } if (!Decls.empty()) ProcessDeclGroup(Decls); if (Indent) Indentation -= Policy.Indentation; }