From 0752e75d9b9093cb88f7e8c505e2511f97b52159 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Wed, 20 Dec 2017 23:17:29 +0000 Subject: [PATCH] Reverting r321223 and its follow-up commit because of failing bots due to Misc/ast-dump-color.cpp. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@321229 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Type.h | 14 +- lib/AST/ASTDumper.cpp | 44 +- lib/AST/TypePrinter.cpp | 10 +- .../Checkers/PaddingChecker.cpp | 658 +++++----- .../dcl.init/dcl.init.ref/p5-examples.cpp | 112 +- test/Frontend/float16.cpp | 652 +++++----- test/Misc/ast-dump-attr.cpp | 422 +++---- test/Misc/ast-dump-color.cpp | 2 +- test/Misc/ast-dump-decl.cpp | 1078 ++++++++--------- test/Misc/ast-dump-invalid.cpp | 128 +- test/OpenMP/dump.cpp | 136 +-- test/Parser/objc-default-ctor-init.mm | 42 +- test/SemaCXX/compound-literal.cpp | 196 +-- test/SemaCXX/sourceranges.cpp | 104 +- test/SemaCXX/warn-redundant-move.cpp | 232 ++-- test/SemaObjCXX/block-cleanup.mm | 32 +- .../SemaTemplate/default-expr-arguments-2.cpp | 4 +- .../SemaTemplate/default-expr-arguments-3.cpp | 110 +- 18 files changed, 1980 insertions(+), 1996 deletions(-) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 882878bb7e..7247838947 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -976,14 +976,16 @@ public: return LHS.Value != RHS.Value; } - static std::string getAsString(SplitQualType split, - const PrintingPolicy &Policy) { - return getAsString(split.Ty, split.Quals, Policy); + std::string getAsString() const { + return getAsString(split()); } - static std::string getAsString(const Type *ty, Qualifiers qs, - const PrintingPolicy &Policy); - std::string getAsString() const; + static std::string getAsString(SplitQualType split) { + return getAsString(split.Ty, split.Quals); + } + + static std::string getAsString(const Type *ty, Qualifiers qs); + std::string getAsString(const PrintingPolicy &Policy) const; void print(raw_ostream &OS, const PrintingPolicy &Policy, diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 8b285db38e..73154ba141 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -99,9 +99,6 @@ namespace { const CommandTraits *Traits; const SourceManager *SM; - /// The policy to use for printing; can be defaulted. - PrintingPolicy PrintPolicy; - /// Pending[i] is an action to dump an entity at level i. llvm::SmallVector, 32> Pending; @@ -210,17 +207,12 @@ namespace { public: ASTDumper(raw_ostream &OS, const CommandTraits *Traits, const SourceManager *SM) - : ASTDumper(OS, Traits, SM, - SM && SM->getDiagnostics().getShowColors()) {} + : OS(OS), Traits(Traits), SM(SM), + ShowColors(SM && SM->getDiagnostics().getShowColors()) { } ASTDumper(raw_ostream &OS, const CommandTraits *Traits, const SourceManager *SM, bool ShowColors) - : ASTDumper(OS, Traits, SM, ShowColors, LangOptions()) {} - ASTDumper(raw_ostream &OS, const CommandTraits *Traits, - const SourceManager *SM, bool ShowColors, - const PrintingPolicy &PrintPolicy) - : OS(OS), Traits(Traits), SM(SM), PrintPolicy(PrintPolicy), - ShowColors(ShowColors) {} + : OS(OS), Traits(Traits), SM(SM), ShowColors(ShowColors) {} void setDeserialize(bool D) { Deserialize = D; } @@ -654,13 +646,13 @@ void ASTDumper::dumpBareType(QualType T, bool Desugar) { ColorScope Color(*this, TypeColor); SplitQualType T_split = T.split(); - OS << "'" << QualType::getAsString(T_split, PrintPolicy) << "'"; + OS << "'" << QualType::getAsString(T_split) << "'"; if (Desugar && !T.isNull()) { // If the type is sugared, also dump a (shallow) desugared type. SplitQualType D_split = T.getSplitDesugaredType(); if (T_split != D_split) - OS << ":'" << QualType::getAsString(D_split, PrintPolicy) << "'"; + OS << ":'" << QualType::getAsString(D_split) << "'"; } } @@ -1195,12 +1187,12 @@ void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { if (const CXXMethodDecl *MD = dyn_cast(D)) { if (MD->size_overridden_methods() != 0) { - auto dumpOverride = [=](const CXXMethodDecl *D) { - SplitQualType T_split = D->getType().split(); - OS << D << " " << D->getParent()->getName() - << "::" << D->getNameAsString() << " '" - << QualType::getAsString(T_split, PrintPolicy) << "'"; - }; + auto dumpOverride = + [=](const CXXMethodDecl *D) { + SplitQualType T_split = D->getType().split(); + OS << D << " " << D->getParent()->getName() << "::" + << D->getNameAsString() << " '" << QualType::getAsString(T_split) << "'"; + }; dumpChild([=] { auto Overrides = MD->overridden_methods(); @@ -2690,18 +2682,15 @@ LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS) const { LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); } LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize) const { - const ASTContext &Ctx = getASTContext(); - ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager(), - false, Ctx.getPrintingPolicy()); + ASTDumper P(OS, &getASTContext().getCommentCommandTraits(), + &getASTContext().getSourceManager()); P.setDeserialize(Deserialize); P.dumpDecl(this); } LLVM_DUMP_METHOD void Decl::dumpColor() const { - const ASTContext &Ctx = getASTContext(); - ASTDumper P(llvm::errs(), &Ctx.getCommentCommandTraits(), - &Ctx.getSourceManager(), /*ShowColors*/ true, - Ctx.getPrintingPolicy()); + ASTDumper P(llvm::errs(), &getASTContext().getCommentCommandTraits(), + &getASTContext().getSourceManager(), /*ShowColors*/true); P.dumpDecl(this); } @@ -2716,8 +2705,7 @@ LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS, while (!DC->isTranslationUnit()) DC = DC->getParent(); ASTContext &Ctx = cast(DC)->getASTContext(); - ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager(), - false, Ctx.getPrintingPolicy()); + ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager()); P.setDeserialize(Deserialize); P.dumpLookups(this, DumpDecls); } diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index c28ada7dcb..b13febc652 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -1712,20 +1712,16 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy, OS << ' '; } -std::string QualType::getAsString() const { - return getAsString(split(), LangOptions()); -} - std::string QualType::getAsString(const PrintingPolicy &Policy) const { std::string S; getAsStringInternal(S, Policy); return S; } -std::string QualType::getAsString(const Type *ty, Qualifiers qs, - const PrintingPolicy &Policy) { +std::string QualType::getAsString(const Type *ty, Qualifiers qs) { std::string buffer; - getAsStringInternal(ty, qs, buffer, Policy); + LangOptions options; + getAsStringInternal(ty, qs, buffer, PrintingPolicy(options)); return buffer; } diff --git a/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp b/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp index b17cd8d373..a51dda6fe8 100644 --- a/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp @@ -1,330 +1,328 @@ -//=======- PaddingChecker.cpp ------------------------------------*- C++ -*-==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a checker that checks for padding that could be -// removed by re-ordering members. -// -//===----------------------------------------------------------------------===// - -#include "ClangSACheckers.h" -#include "clang/AST/CharUnits.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/RecordLayout.h" -#include "clang/AST/RecursiveASTVisitor.h" -#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" -#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/Checker.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/raw_ostream.h" -#include - -using namespace clang; -using namespace ento; - -namespace { -class PaddingChecker : public Checker> { -private: - mutable std::unique_ptr PaddingBug; - mutable int64_t AllowedPad; - mutable BugReporter *BR; - -public: - void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR, - BugReporter &BRArg) const { - BR = &BRArg; - AllowedPad = - MGR.getAnalyzerOptions().getOptionAsInteger("AllowedPad", 24, this); - assert(AllowedPad >= 0 && "AllowedPad option should be non-negative"); - - // The calls to checkAST* from AnalysisConsumer don't - // visit template instantiations or lambda classes. We - // want to visit those, so we make our own RecursiveASTVisitor. - struct LocalVisitor : public RecursiveASTVisitor { - const PaddingChecker *Checker; - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return true; } - explicit LocalVisitor(const PaddingChecker *Checker) : Checker(Checker) {} - bool VisitRecordDecl(const RecordDecl *RD) { - Checker->visitRecord(RD); - return true; - } - bool VisitVarDecl(const VarDecl *VD) { - Checker->visitVariable(VD); - return true; - } - // TODO: Visit array new and mallocs for arrays. - }; - - LocalVisitor visitor(this); - visitor.TraverseDecl(const_cast(TUD)); - } - - /// \brief Look for records of overly padded types. If padding * - /// PadMultiplier exceeds AllowedPad, then generate a report. - /// PadMultiplier is used to share code with the array padding - /// checker. - void visitRecord(const RecordDecl *RD, uint64_t PadMultiplier = 1) const { - if (shouldSkipDecl(RD)) - return; - - auto &ASTContext = RD->getASTContext(); - const ASTRecordLayout &RL = ASTContext.getASTRecordLayout(RD); - assert(llvm::isPowerOf2_64(RL.getAlignment().getQuantity())); - - CharUnits BaselinePad = calculateBaselinePad(RD, ASTContext, RL); - if (BaselinePad.isZero()) - return; - - CharUnits OptimalPad; - SmallVector OptimalFieldsOrder; - std::tie(OptimalPad, OptimalFieldsOrder) = - calculateOptimalPad(RD, ASTContext, RL); - - CharUnits DiffPad = PadMultiplier * (BaselinePad - OptimalPad); - if (DiffPad.getQuantity() <= AllowedPad) { - assert(!DiffPad.isNegative() && "DiffPad should not be negative"); - // There is not enough excess padding to trigger a warning. - return; - } - reportRecord(RD, BaselinePad, OptimalPad, OptimalFieldsOrder); - } - - /// \brief Look for arrays of overly padded types. If the padding of the - /// array type exceeds AllowedPad, then generate a report. - void visitVariable(const VarDecl *VD) const { - const ArrayType *ArrTy = VD->getType()->getAsArrayTypeUnsafe(); - if (ArrTy == nullptr) - return; - uint64_t Elts = 0; - if (const ConstantArrayType *CArrTy = dyn_cast(ArrTy)) - Elts = CArrTy->getSize().getZExtValue(); - if (Elts == 0) - return; - const RecordType *RT = ArrTy->getElementType()->getAs(); - if (RT == nullptr) - return; - - // TODO: Recurse into the fields and base classes to see if any - // of those have excess padding. - visitRecord(RT->getDecl(), Elts); - } - - bool shouldSkipDecl(const RecordDecl *RD) const { - auto Location = RD->getLocation(); - // If the construct doesn't have a source file, then it's not something - // we want to diagnose. - if (!Location.isValid()) - return true; - SrcMgr::CharacteristicKind Kind = - BR->getSourceManager().getFileCharacteristic(Location); - // Throw out all records that come from system headers. - if (Kind != SrcMgr::C_User) - return true; - - // Not going to attempt to optimize unions. - if (RD->isUnion()) - return true; - // How do you reorder fields if you haven't got any? - if (RD->field_empty()) - return true; - if (auto *CXXRD = dyn_cast(RD)) { - // Tail padding with base classes ends up being very complicated. - // We will skip objects with base classes for now. - if (CXXRD->getNumBases() != 0) - return true; - // Virtual bases are complicated, skipping those for now. - if (CXXRD->getNumVBases() != 0) - return true; - // Can't layout a template, so skip it. We do still layout the - // instantiations though. - if (CXXRD->getTypeForDecl()->isDependentType()) - return true; - if (CXXRD->getTypeForDecl()->isInstantiationDependentType()) - return true; - } - auto IsTrickyField = [](const FieldDecl *FD) -> bool { - // Bitfield layout is hard. - if (FD->isBitField()) - return true; - - // Variable length arrays are tricky too. - QualType Ty = FD->getType(); - if (Ty->isIncompleteArrayType()) - return true; - return false; - }; - - if (std::any_of(RD->field_begin(), RD->field_end(), IsTrickyField)) - return true; - return false; - } - - static CharUnits calculateBaselinePad(const RecordDecl *RD, - const ASTContext &ASTContext, - const ASTRecordLayout &RL) { - CharUnits PaddingSum; - CharUnits Offset = ASTContext.toCharUnitsFromBits(RL.getFieldOffset(0)); - for (const FieldDecl *FD : RD->fields()) { - // This checker only cares about the padded size of the - // field, and not the data size. If the field is a record - // with tail padding, then we won't put that number in our - // total because reordering fields won't fix that problem. - CharUnits FieldSize = ASTContext.getTypeSizeInChars(FD->getType()); - auto FieldOffsetBits = RL.getFieldOffset(FD->getFieldIndex()); - CharUnits FieldOffset = ASTContext.toCharUnitsFromBits(FieldOffsetBits); - PaddingSum += (FieldOffset - Offset); - Offset = FieldOffset + FieldSize; - } - PaddingSum += RL.getSize() - Offset; - return PaddingSum; - } - - /// Optimal padding overview: - /// 1. Find a close approximation to where we can place our first field. - /// This will usually be at offset 0. - /// 2. Try to find the best field that can legally be placed at the current - /// offset. - /// a. "Best" is the largest alignment that is legal, but smallest size. - /// This is to account for overly aligned types. - /// 3. If no fields can fit, pad by rounding the current offset up to the - /// smallest alignment requirement of our fields. Measure and track the - // amount of padding added. Go back to 2. - /// 4. Increment the current offset by the size of the chosen field. - /// 5. Remove the chosen field from the set of future possibilities. - /// 6. Go back to 2 if there are still unplaced fields. - /// 7. Add tail padding by rounding the current offset up to the structure - /// alignment. Track the amount of padding added. - - static std::pair> - calculateOptimalPad(const RecordDecl *RD, const ASTContext &ASTContext, - const ASTRecordLayout &RL) { - struct FieldInfo { - CharUnits Align; - CharUnits Size; - const FieldDecl *Field; - bool operator<(const FieldInfo &RHS) const { - // Order from small alignments to large alignments, - // then large sizes to small sizes. - // then large field indices to small field indices - return std::make_tuple(Align, -Size, - Field ? -static_cast(Field->getFieldIndex()) - : 0) < - std::make_tuple( - RHS.Align, -RHS.Size, - RHS.Field ? -static_cast(RHS.Field->getFieldIndex()) - : 0); - } - }; - SmallVector Fields; - auto GatherSizesAndAlignments = [](const FieldDecl *FD) { - FieldInfo RetVal; - RetVal.Field = FD; - auto &Ctx = FD->getASTContext(); - std::tie(RetVal.Size, RetVal.Align) = - Ctx.getTypeInfoInChars(FD->getType()); - assert(llvm::isPowerOf2_64(RetVal.Align.getQuantity())); - if (auto Max = FD->getMaxAlignment()) - RetVal.Align = std::max(Ctx.toCharUnitsFromBits(Max), RetVal.Align); - return RetVal; - }; - std::transform(RD->field_begin(), RD->field_end(), - std::back_inserter(Fields), GatherSizesAndAlignments); - std::sort(Fields.begin(), Fields.end()); - // This lets us skip over vptrs and non-virtual bases, - // so that we can just worry about the fields in our object. - // Note that this does cause us to miss some cases where we - // could pack more bytes in to a base class's tail padding. - CharUnits NewOffset = ASTContext.toCharUnitsFromBits(RL.getFieldOffset(0)); - CharUnits NewPad; - SmallVector OptimalFieldsOrder; - while (!Fields.empty()) { - unsigned TrailingZeros = - llvm::countTrailingZeros((unsigned long long)NewOffset.getQuantity()); - // If NewOffset is zero, then countTrailingZeros will be 64. Shifting - // 64 will overflow our unsigned long long. Shifting 63 will turn - // our long long (and CharUnits internal type) negative. So shift 62. - long long CurAlignmentBits = 1ull << (std::min)(TrailingZeros, 62u); - CharUnits CurAlignment = CharUnits::fromQuantity(CurAlignmentBits); - FieldInfo InsertPoint = {CurAlignment, CharUnits::Zero(), nullptr}; - auto CurBegin = Fields.begin(); - auto CurEnd = Fields.end(); - - // In the typical case, this will find the last element - // of the vector. We won't find a middle element unless - // we started on a poorly aligned address or have an overly - // aligned field. - auto Iter = std::upper_bound(CurBegin, CurEnd, InsertPoint); - if (Iter != CurBegin) { - // We found a field that we can layout with the current alignment. - --Iter; - NewOffset += Iter->Size; - OptimalFieldsOrder.push_back(Iter->Field); - Fields.erase(Iter); - } else { - // We are poorly aligned, and we need to pad in order to layout another - // field. Round up to at least the smallest field alignment that we - // currently have. - CharUnits NextOffset = NewOffset.alignTo(Fields[0].Align); - NewPad += NextOffset - NewOffset; - NewOffset = NextOffset; - } - } - // Calculate tail padding. - CharUnits NewSize = NewOffset.alignTo(RL.getAlignment()); - NewPad += NewSize - NewOffset; - return {NewPad, std::move(OptimalFieldsOrder)}; - } - - void reportRecord( - const RecordDecl *RD, CharUnits BaselinePad, CharUnits OptimalPad, - const SmallVector &OptimalFieldsOrder) const { - if (!PaddingBug) - PaddingBug = - llvm::make_unique(this, "Excessive Padding", "Performance"); - - SmallString<100> Buf; - llvm::raw_svector_ostream Os(Buf); - Os << "Excessive padding in '"; - Os << QualType::getAsString(RD->getTypeForDecl(), Qualifiers(), - LangOptions()) - << "'"; - - if (auto *TSD = dyn_cast(RD)) { - // TODO: make this show up better in the console output and in - // the HTML. Maybe just make it show up in HTML like the path - // diagnostics show. - SourceLocation ILoc = TSD->getPointOfInstantiation(); - if (ILoc.isValid()) - Os << " instantiated here: " - << ILoc.printToString(BR->getSourceManager()); - } - - Os << " (" << BaselinePad.getQuantity() << " padding bytes, where " - << OptimalPad.getQuantity() << " is optimal). \n" - << "Optimal fields order: \n"; - for (const auto *FD : OptimalFieldsOrder) - Os << FD->getName() << ", \n"; - Os << "consider reordering the fields or adding explicit padding " - "members."; - - PathDiagnosticLocation CELoc = - PathDiagnosticLocation::create(RD, BR->getSourceManager()); - auto Report = llvm::make_unique(*PaddingBug, Os.str(), CELoc); - Report->setDeclWithIssue(RD); - Report->addRange(RD->getSourceRange()); - BR->emitReport(std::move(Report)); - } -}; -} - -void ento::registerPaddingChecker(CheckerManager &Mgr) { - Mgr.registerChecker(); -} +//=======- PaddingChecker.cpp ------------------------------------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a checker that checks for padding that could be +// removed by re-ordering members. +// +//===----------------------------------------------------------------------===// + +#include "ClangSACheckers.h" +#include "clang/AST/CharUnits.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include + +using namespace clang; +using namespace ento; + +namespace { +class PaddingChecker : public Checker> { +private: + mutable std::unique_ptr PaddingBug; + mutable int64_t AllowedPad; + mutable BugReporter *BR; + +public: + void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR, + BugReporter &BRArg) const { + BR = &BRArg; + AllowedPad = + MGR.getAnalyzerOptions().getOptionAsInteger("AllowedPad", 24, this); + assert(AllowedPad >= 0 && "AllowedPad option should be non-negative"); + + // The calls to checkAST* from AnalysisConsumer don't + // visit template instantiations or lambda classes. We + // want to visit those, so we make our own RecursiveASTVisitor. + struct LocalVisitor : public RecursiveASTVisitor { + const PaddingChecker *Checker; + bool shouldVisitTemplateInstantiations() const { return true; } + bool shouldVisitImplicitCode() const { return true; } + explicit LocalVisitor(const PaddingChecker *Checker) : Checker(Checker) {} + bool VisitRecordDecl(const RecordDecl *RD) { + Checker->visitRecord(RD); + return true; + } + bool VisitVarDecl(const VarDecl *VD) { + Checker->visitVariable(VD); + return true; + } + // TODO: Visit array new and mallocs for arrays. + }; + + LocalVisitor visitor(this); + visitor.TraverseDecl(const_cast(TUD)); + } + + /// \brief Look for records of overly padded types. If padding * + /// PadMultiplier exceeds AllowedPad, then generate a report. + /// PadMultiplier is used to share code with the array padding + /// checker. + void visitRecord(const RecordDecl *RD, uint64_t PadMultiplier = 1) const { + if (shouldSkipDecl(RD)) + return; + + auto &ASTContext = RD->getASTContext(); + const ASTRecordLayout &RL = ASTContext.getASTRecordLayout(RD); + assert(llvm::isPowerOf2_64(RL.getAlignment().getQuantity())); + + CharUnits BaselinePad = calculateBaselinePad(RD, ASTContext, RL); + if (BaselinePad.isZero()) + return; + + CharUnits OptimalPad; + SmallVector OptimalFieldsOrder; + std::tie(OptimalPad, OptimalFieldsOrder) = + calculateOptimalPad(RD, ASTContext, RL); + + CharUnits DiffPad = PadMultiplier * (BaselinePad - OptimalPad); + if (DiffPad.getQuantity() <= AllowedPad) { + assert(!DiffPad.isNegative() && "DiffPad should not be negative"); + // There is not enough excess padding to trigger a warning. + return; + } + reportRecord(RD, BaselinePad, OptimalPad, OptimalFieldsOrder); + } + + /// \brief Look for arrays of overly padded types. If the padding of the + /// array type exceeds AllowedPad, then generate a report. + void visitVariable(const VarDecl *VD) const { + const ArrayType *ArrTy = VD->getType()->getAsArrayTypeUnsafe(); + if (ArrTy == nullptr) + return; + uint64_t Elts = 0; + if (const ConstantArrayType *CArrTy = dyn_cast(ArrTy)) + Elts = CArrTy->getSize().getZExtValue(); + if (Elts == 0) + return; + const RecordType *RT = ArrTy->getElementType()->getAs(); + if (RT == nullptr) + return; + + // TODO: Recurse into the fields and base classes to see if any + // of those have excess padding. + visitRecord(RT->getDecl(), Elts); + } + + bool shouldSkipDecl(const RecordDecl *RD) const { + auto Location = RD->getLocation(); + // If the construct doesn't have a source file, then it's not something + // we want to diagnose. + if (!Location.isValid()) + return true; + SrcMgr::CharacteristicKind Kind = + BR->getSourceManager().getFileCharacteristic(Location); + // Throw out all records that come from system headers. + if (Kind != SrcMgr::C_User) + return true; + + // Not going to attempt to optimize unions. + if (RD->isUnion()) + return true; + // How do you reorder fields if you haven't got any? + if (RD->field_empty()) + return true; + if (auto *CXXRD = dyn_cast(RD)) { + // Tail padding with base classes ends up being very complicated. + // We will skip objects with base classes for now. + if (CXXRD->getNumBases() != 0) + return true; + // Virtual bases are complicated, skipping those for now. + if (CXXRD->getNumVBases() != 0) + return true; + // Can't layout a template, so skip it. We do still layout the + // instantiations though. + if (CXXRD->getTypeForDecl()->isDependentType()) + return true; + if (CXXRD->getTypeForDecl()->isInstantiationDependentType()) + return true; + } + auto IsTrickyField = [](const FieldDecl *FD) -> bool { + // Bitfield layout is hard. + if (FD->isBitField()) + return true; + + // Variable length arrays are tricky too. + QualType Ty = FD->getType(); + if (Ty->isIncompleteArrayType()) + return true; + return false; + }; + + if (std::any_of(RD->field_begin(), RD->field_end(), IsTrickyField)) + return true; + return false; + } + + static CharUnits calculateBaselinePad(const RecordDecl *RD, + const ASTContext &ASTContext, + const ASTRecordLayout &RL) { + CharUnits PaddingSum; + CharUnits Offset = ASTContext.toCharUnitsFromBits(RL.getFieldOffset(0)); + for (const FieldDecl *FD : RD->fields()) { + // This checker only cares about the padded size of the + // field, and not the data size. If the field is a record + // with tail padding, then we won't put that number in our + // total because reordering fields won't fix that problem. + CharUnits FieldSize = ASTContext.getTypeSizeInChars(FD->getType()); + auto FieldOffsetBits = RL.getFieldOffset(FD->getFieldIndex()); + CharUnits FieldOffset = ASTContext.toCharUnitsFromBits(FieldOffsetBits); + PaddingSum += (FieldOffset - Offset); + Offset = FieldOffset + FieldSize; + } + PaddingSum += RL.getSize() - Offset; + return PaddingSum; + } + + /// Optimal padding overview: + /// 1. Find a close approximation to where we can place our first field. + /// This will usually be at offset 0. + /// 2. Try to find the best field that can legally be placed at the current + /// offset. + /// a. "Best" is the largest alignment that is legal, but smallest size. + /// This is to account for overly aligned types. + /// 3. If no fields can fit, pad by rounding the current offset up to the + /// smallest alignment requirement of our fields. Measure and track the + // amount of padding added. Go back to 2. + /// 4. Increment the current offset by the size of the chosen field. + /// 5. Remove the chosen field from the set of future possibilities. + /// 6. Go back to 2 if there are still unplaced fields. + /// 7. Add tail padding by rounding the current offset up to the structure + /// alignment. Track the amount of padding added. + + static std::pair> + calculateOptimalPad(const RecordDecl *RD, const ASTContext &ASTContext, + const ASTRecordLayout &RL) { + struct FieldInfo { + CharUnits Align; + CharUnits Size; + const FieldDecl *Field; + bool operator<(const FieldInfo &RHS) const { + // Order from small alignments to large alignments, + // then large sizes to small sizes. + // then large field indices to small field indices + return std::make_tuple(Align, -Size, + Field ? -static_cast(Field->getFieldIndex()) + : 0) < + std::make_tuple( + RHS.Align, -RHS.Size, + RHS.Field ? -static_cast(RHS.Field->getFieldIndex()) + : 0); + } + }; + SmallVector Fields; + auto GatherSizesAndAlignments = [](const FieldDecl *FD) { + FieldInfo RetVal; + RetVal.Field = FD; + auto &Ctx = FD->getASTContext(); + std::tie(RetVal.Size, RetVal.Align) = + Ctx.getTypeInfoInChars(FD->getType()); + assert(llvm::isPowerOf2_64(RetVal.Align.getQuantity())); + if (auto Max = FD->getMaxAlignment()) + RetVal.Align = std::max(Ctx.toCharUnitsFromBits(Max), RetVal.Align); + return RetVal; + }; + std::transform(RD->field_begin(), RD->field_end(), + std::back_inserter(Fields), GatherSizesAndAlignments); + std::sort(Fields.begin(), Fields.end()); + // This lets us skip over vptrs and non-virtual bases, + // so that we can just worry about the fields in our object. + // Note that this does cause us to miss some cases where we + // could pack more bytes in to a base class's tail padding. + CharUnits NewOffset = ASTContext.toCharUnitsFromBits(RL.getFieldOffset(0)); + CharUnits NewPad; + SmallVector OptimalFieldsOrder; + while (!Fields.empty()) { + unsigned TrailingZeros = + llvm::countTrailingZeros((unsigned long long)NewOffset.getQuantity()); + // If NewOffset is zero, then countTrailingZeros will be 64. Shifting + // 64 will overflow our unsigned long long. Shifting 63 will turn + // our long long (and CharUnits internal type) negative. So shift 62. + long long CurAlignmentBits = 1ull << (std::min)(TrailingZeros, 62u); + CharUnits CurAlignment = CharUnits::fromQuantity(CurAlignmentBits); + FieldInfo InsertPoint = {CurAlignment, CharUnits::Zero(), nullptr}; + auto CurBegin = Fields.begin(); + auto CurEnd = Fields.end(); + + // In the typical case, this will find the last element + // of the vector. We won't find a middle element unless + // we started on a poorly aligned address or have an overly + // aligned field. + auto Iter = std::upper_bound(CurBegin, CurEnd, InsertPoint); + if (Iter != CurBegin) { + // We found a field that we can layout with the current alignment. + --Iter; + NewOffset += Iter->Size; + OptimalFieldsOrder.push_back(Iter->Field); + Fields.erase(Iter); + } else { + // We are poorly aligned, and we need to pad in order to layout another + // field. Round up to at least the smallest field alignment that we + // currently have. + CharUnits NextOffset = NewOffset.alignTo(Fields[0].Align); + NewPad += NextOffset - NewOffset; + NewOffset = NextOffset; + } + } + // Calculate tail padding. + CharUnits NewSize = NewOffset.alignTo(RL.getAlignment()); + NewPad += NewSize - NewOffset; + return {NewPad, std::move(OptimalFieldsOrder)}; + } + + void reportRecord( + const RecordDecl *RD, CharUnits BaselinePad, CharUnits OptimalPad, + const SmallVector &OptimalFieldsOrder) const { + if (!PaddingBug) + PaddingBug = + llvm::make_unique(this, "Excessive Padding", "Performance"); + + SmallString<100> Buf; + llvm::raw_svector_ostream Os(Buf); + Os << "Excessive padding in '"; + Os << QualType::getAsString(RD->getTypeForDecl(), Qualifiers()) << "'"; + + if (auto *TSD = dyn_cast(RD)) { + // TODO: make this show up better in the console output and in + // the HTML. Maybe just make it show up in HTML like the path + // diagnostics show. + SourceLocation ILoc = TSD->getPointOfInstantiation(); + if (ILoc.isValid()) + Os << " instantiated here: " + << ILoc.printToString(BR->getSourceManager()); + } + + Os << " (" << BaselinePad.getQuantity() << " padding bytes, where " + << OptimalPad.getQuantity() << " is optimal). \n" + << "Optimal fields order: \n"; + for (const auto *FD : OptimalFieldsOrder) + Os << FD->getName() << ", \n"; + Os << "consider reordering the fields or adding explicit padding " + "members."; + + PathDiagnosticLocation CELoc = + PathDiagnosticLocation::create(RD, BR->getSourceManager()); + auto Report = llvm::make_unique(*PaddingBug, Os.str(), CELoc); + Report->setDeclWithIssue(RD); + Report->addRange(RD->getSourceRange()); + BR->emitReport(std::move(Report)); + } +}; +} + +void ento::registerPaddingChecker(CheckerManager &Mgr) { + Mgr.registerChecker(); +} diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp index 46593b7e2a..052349c8e2 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp @@ -1,56 +1,56 @@ -// RUN: %clang_cc1 -ast-dump %s 2>&1 | FileCheck %s - -// CHECK-LABEL: example0 -void example0() { - double d = 2.0; - // CHECK: VarDecl{{.*}}rd 'double &' - // CHECK-NEXT: DeclRefExpr - double &rd = d; - // CHECK: VarDecl{{.*}}rcd 'const double &' - // CHECK-NEXT: ImplicitCastExpr{{.*}}'const double' lvalue - const double &rcd = d; -} - -struct A { }; -struct B : A { } b; - -// CHECK-LABEL: example1 -void example1() { - // CHECK: VarDecl{{.*}}ra 'A &' - // CHECK: ImplicitCastExpr{{.*}}'A' lvalue - A &ra = b; - // CHECK: VarDecl{{.*}}rca 'const A &' - // CHECK: ImplicitCastExpr{{.*}}'const A' lvalue - // CHECK-NOT: MaterializeTemporaryExpr - // CHECK: ImplicitCastExpr{{.*}}'const B' lvalue - const A& rca = b; -} - -extern B f(); - -struct X { - operator B(); -} x; - -// CHECK-LABEL: example2 -void example2() { - // CHECK: VarDecl{{.*}}rca 'const A &' - // CHECK: ImplicitCastExpr{{.*}}'const A' lvalue - // CHECK: MaterializeTemporaryExpr{{.*}}'const B' - // CHECK: ImplicitCastExpr{{.*}}'const B' - // CHECK: CallExpr{{.*}}B - const A &rca = f(); - // CHECK: VarDecl{{.*}}r 'const A &' - // CHECK: ImplicitCastExpr{{.*}}'const A' lvalue - // CHECK: MaterializeTemporaryExpr{{.*}}'const B' - // CHECK: ImplicitCastExpr{{.*}}'const B' - // CHECK: CXXMemberCallExpr{{.*}}'B' - const A& r = x; -} - -// CHECK-LABEL: example3 -void example3() { - // CHECK: VarDecl{{.*}}rcd2 'const double &' - // CHECK: ImplicitCastExpr{{.*}} - const double& rcd2 = 2; -} +// RUN: %clang_cc1 -ast-dump %s 2>&1 | FileCheck %s + +// CHECK-LABEL: example0 +void example0() { + double d = 2.0; + // CHECK: VarDecl{{.*}}rd 'double &' + // CHECK-NEXT: DeclRefExpr + double &rd = d; + // CHECK: VarDecl{{.*}}rcd 'const double &' + // CHECK-NEXT: ImplicitCastExpr{{.*}}'const double' lvalue + const double &rcd = d; +} + +struct A { }; +struct B : A { } b; + +// CHECK-LABEL: example1 +void example1() { + // CHECK: VarDecl{{.*}}ra 'struct A &' + // CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue + A &ra = b; + // CHECK: VarDecl{{.*}}rca 'const struct A &' + // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue + // CHECK-NOT: MaterializeTemporaryExpr + // CHECK: ImplicitCastExpr{{.*}}'const struct B' lvalue + const A& rca = b; +} + +extern B f(); + +struct X { + operator B(); +} x; + +// CHECK-LABEL: example2 +void example2() { + // CHECK: VarDecl{{.*}}rca 'const struct A &' + // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue + // CHECK: MaterializeTemporaryExpr{{.*}}'const struct B' + // CHECK: ImplicitCastExpr{{.*}}'const struct B' + // CHECK: CallExpr{{.*}}B + const A &rca = f(); + // CHECK: VarDecl{{.*}}r 'const struct A &' + // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue + // CHECK: MaterializeTemporaryExpr{{.*}}'const struct B' + // CHECK: ImplicitCastExpr{{.*}}'const struct B' + // CHECK: CXXMemberCallExpr{{.*}}'struct B' + const A& r = x; +} + +// CHECK-LABEL: example3 +void example3() { + // CHECK: VarDecl{{.*}}rcd2 'const double &' + // CHECK: ImplicitCastExpr{{.*}} + const double& rcd2 = 2; +} diff --git a/test/Frontend/float16.cpp b/test/Frontend/float16.cpp index aa65270c75..febd6b8e36 100644 --- a/test/Frontend/float16.cpp +++ b/test/Frontend/float16.cpp @@ -1,326 +1,326 @@ -// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s --strict-whitespace -// RUN: %clang_cc1 -std=c++11 -ast-dump -fnative-half-type %s | FileCheck %s --check-prefix=CHECK-NATIVE --strict-whitespace - -/* Various contexts where type _Float16 can appear. */ - -/* Namespace */ -namespace { - _Float16 f1n; - _Float16 f2n = 33.f16; - _Float16 arr1n[10]; - _Float16 arr2n[] = { 1.2, 3.0, 3.e4 }; - const volatile _Float16 func1n(const _Float16 &arg) { - return arg + f2n + arr1n[4] - arr2n[1]; - } -} - -//CHECK: |-NamespaceDecl -//CHECK-NEXT: | |-VarDecl {{.*}} f1n '_Float16' -//CHECK-NEXT: | |-VarDecl {{.*}} f2n '_Float16' cinit -//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 3.300000e+01 -//CHECK-NEXT: | |-VarDecl {{.*}} arr1n '_Float16 [10]' -//CHECK-NEXT: | |-VarDecl {{.*}} arr2n '_Float16 [3]' cinit -//CHECK-NEXT: | | `-InitListExpr {{.*}} '_Float16 [3]' -//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00 -//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00 -//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 3.000000e+04 -//CHECK-NEXT: | `-FunctionDecl {{.*}} func1n 'const volatile _Float16 (const _Float16 &)' - -/* File */ -_Float16 f1f; -_Float16 f2f = 32.4; -_Float16 arr1f[10]; -_Float16 arr2f[] = { -1.2, -3.0, -3.e4 }; -_Float16 func1f(_Float16 arg); - -//CHECK: |-VarDecl {{.*}} f1f '_Float16' -//CHECK-NEXT: |-VarDecl {{.*}} f2f '_Float16' cinit -//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 3.240000e+01 -//CHECK-NEXT: |-VarDecl {{.*}} arr1f '_Float16 [10]' -//CHECK-NEXT: |-VarDecl {{.*}} arr2f '_Float16 [3]' cinit -//CHECK-NEXT: | `-InitListExpr {{.*}} '_Float16 [3]' -//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | `-UnaryOperator {{.*}} 'double' prefix '-' -//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00 -//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | `-UnaryOperator {{.*}} 'double' prefix '-' -//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00 -//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | `-UnaryOperator {{.*}} 'double' prefix '-' -//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 3.000000e+04 -//CHECK-NEXT: |-FunctionDecl {{.*}} func1f '_Float16 (_Float16)' -//CHECK-NEXT: | `-ParmVarDecl {{.*}} arg '_Float16' - - -// Mixing __fp16 and Float16 types: -// The _Float16 type is first converted to __fp16 type and then the operation -// is completed as if both operands were of __fp16 type. - -__fp16 B = -0.1; -auto C = -1.0f16 + B; - -// When we do *not* have native half types, we expect __fp16 to be promoted to -// float, and consequently also _Float16 promotions to float: - -//CHECK: -VarDecl {{.*}} used B '__fp16' cinit -//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__fp16' -//CHECK-NEXT: | `-UnaryOperator {{.*}} 'double' prefix '-' -//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 1.000000e-01 -//CHECK-NEXT: |-VarDecl {{.*}} C 'float':'float' cinit -//CHECK-NEXT: | `-BinaryOperator {{.*}} 'float' '+' -//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'float' -//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16' prefix '-' -//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00 -//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'float' -//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__fp16' -//CHECK-NEXT: | `-DeclRefExpr {{.*}} '__fp16' lvalue Var 0x{{.*}} 'B' '__fp16' - -// When do have native half types, we expect to see promotions to fp16: - -//CHECK-NATIVE: |-VarDecl {{.*}} used B '__fp16' cinit -//CHECK-NATIVE: | `-ImplicitCastExpr {{.*}} '__fp16' -//CHECK-NATIVE: | `-UnaryOperator {{.*}} 'double' prefix '-' -//CHECK-NATIVE: | `-FloatingLiteral {{.*}} 'double' 1.000000e-01 -//CHECK-NATIVE: |-VarDecl {{.*}} C '__fp16':'__fp16' cinit -//CHECK-NATIVE: | `-BinaryOperator {{.*}} '__fp16' '+' -//CHECK-NATIVE: | |-ImplicitCastExpr {{.*}} '__fp16' -//CHECK-NATIVE: | | `-UnaryOperator {{.*}} '_Float16' prefix '-' -//CHECK-NATIVE: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00 -//CHECK-NATIVE: | `-ImplicitCastExpr {{.*}} '__fp16' -//CHECK-NATIVE: | `-DeclRefExpr {{.*}} '__fp16' lvalue Var 0x{{.*}} 'B' '__fp16' - - -/* Class */ - -class C1 { - _Float16 f1c; - static const _Float16 f2c; - volatile _Float16 f3c; -public: - C1(_Float16 arg) : f1c(arg), f3c(arg) { } - _Float16 func1c(_Float16 arg ) { - return f1c + arg; - } - static _Float16 func2c(_Float16 arg) { - return arg * C1::f2c; - } -}; - -//CHECK: |-CXXRecordDecl {{.*}} referenced class C1 definition -//CHECK: | |-CXXRecordDecl {{.*}} implicit referenced class C1 -//CHECK-NEXT: | |-FieldDecl {{.*}} referenced f1c '_Float16' -//CHECK-NEXT: | |-VarDecl {{.*}} used f2c 'const _Float16' static -//CHECK-NEXT: | |-FieldDecl {{.*}} f3c 'volatile _Float16' -//CHECK-NEXT: | |-AccessSpecDecl -//CHECK-NEXT: | |-CXXConstructorDecl {{.*}} used C1 'void (_Float16) -//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16' -//CHECK-NEXT: | | |-CXXCtorInitializer Field {{.*}} 'f1c' '_Float16' -//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16' -//CHECK-NEXT: | | |-CXXCtorInitializer Field {{.*}} 'f3c' 'volatile _Float16' -//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16' -//CHECK-NEXT: | | `-CompoundStmt -//CHECK-NEXT: | |-CXXMethodDecl {{.*}} used func1c '_Float16 (_Float16) -//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16' -//CHECK-NEXT: | | `-CompoundStmt -//CHECK-NEXT: | | `-ReturnStmt -//CHECK-NEXT: | | `-BinaryOperator {{.*}} '_Float16' '+' -//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | | `-MemberExpr {{.*}} '_Float16' lvalue ->f1c 0x{{.*}} -//CHECK-NEXT: | | | `-CXXThisExpr {{.*}} 'C1 *' this -//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16' -//CHECK-NEXT: | |-CXXMethodDecl {{.*}} used func2c '_Float16 (_Float16)' static -//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16' -//CHECK-NEXT: | | `-CompoundStmt -//CHECK-NEXT: | | `-ReturnStmt -//CHECK-NEXT: | | `-BinaryOperator {{.*}} '_Float16' '*' -//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16' -//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'const _Float16' lvalue Var 0x{{.*}} 'f2c' 'const _Float16' - - -/* Template */ - -template C func1t(C arg) { - return arg * 2.f16; -} - -//CHECK: |-FunctionTemplateDecl {{.*}} func1t -//CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} C -//CHECK-NEXT: | |-FunctionDecl {{.*}} func1t 'C (C)' -//CHECK-NEXT: | | |-ParmVarDecl {{.*}} referenced arg 'C' -//CHECK-NEXT: | | `-CompoundStmt -//CHECK-NEXT: | | `-ReturnStmt -//CHECK-NEXT: | | `-BinaryOperator {{.*}} '' '*' -//CHECK-NEXT: | | |-DeclRefExpr {{.*}} 'C' lvalue ParmVar {{.*}} 'arg' 'C' -//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 2.000000e+00 -//CHECK-NEXT: | `-FunctionDecl {{.*}} used func1t '_Float16 (_Float16)' -//CHECK-NEXT: | |-TemplateArgument type '_Float16' -//CHECK-NEXT: | |-ParmVarDecl {{.*}} used arg '_Float16':'_Float16' -//CHECK-NEXT: | `-CompoundStmt -//CHECK-NEXT: | `-ReturnStmt -//CHECK-NEXT: | `-BinaryOperator {{.*}} '_Float16' '*' -//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16':'_Float16' -//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16':'_Float16' lvalue ParmVar {{.*}} 'arg' '_Float16':'_Float16' -//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 2.000000e+00 - - -template struct S1 { - C mem1; -}; - -//CHECK: |-ClassTemplateDecl {{.*}} S1 -//CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} referenced class depth 0 index 0 C -//CHECK-NEXT: | |-CXXRecordDecl {{.*}} struct S1 definition -//CHECK: | | |-CXXRecordDecl {{.*}} implicit struct S1 -//CHECK-NEXT: | | `-FieldDecl {{.*}} mem1 'C' -//CHECK-NEXT: | `-ClassTemplateSpecialization {{.*}} 'S1' - -template <> struct S1<_Float16> { - _Float16 mem2; -}; - - -/* Local */ - -extern int printf (const char *__restrict __format, ...); - -int main(void) { - _Float16 f1l = 1e3f16; -//CHECK: | `-VarDecl {{.*}} used f1l '_Float16' cinit -//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+03 - - _Float16 f2l = -0.f16; -//CHECK: | `-VarDecl {{.*}} used f2l '_Float16' cinit -//CHECK-NEXT: | `-UnaryOperator {{.*}} '_Float16' prefix '-' -//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 0.000000e+00 - - _Float16 f3l = 1.000976562; -//CHECK: | `-VarDecl {{.*}} used f3l '_Float16' cinit -//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 1.000977e+00 - - C1 c1(f1l); -//CHECK: | `-VarDecl{{.*}} used c1 'C1' callinit -//CHECK-NEXT: | `-CXXConstructExpr {{.*}} 'C1' 'void (_Float16) -//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var 0x{{.*}} 'f1l' '_Float16' - - S1<_Float16> s1 = { 132.f16 }; -//CHECK: | `-VarDecl {{.*}} used s1 'S1<_Float16>':'S1<_Float16>' cinit -//CHECK-NEXT: | `-InitListExpr {{.*}} 'S1<_Float16>':'S1<_Float16>' -//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.320000e+02 - - _Float16 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) + - func1t(f1l) + s1.mem2 - f1n + f2n; -//CHECK: | `-VarDecl {{.*}} used f4l '_Float16' cinit -//CHECK-NEXT: | `-BinaryOperator {{.*}} '_Float16' '+' -//CHECK-NEXT: | |-BinaryOperator {{.*}} '_Float16' '-' -//CHECK-NEXT: | | |-BinaryOperator {{.*}} '_Float16' '+' -//CHECK-NEXT: | | | |-BinaryOperator {{.*}} '_Float16' '+' -//CHECK-NEXT: | | | | |-BinaryOperator {{.*}} '_Float16' '+' -//CHECK-NEXT: | | | | | |-BinaryOperator {{.*}} '_Float16' '+' -//CHECK-NEXT: | | | | | | |-BinaryOperator {{.*}} '_Float16' '+' -//CHECK-NEXT: | | | | | | | |-CallExpr {{.*}} '_Float16' -//CHECK-NEXT: | | | | | | | | |-ImplicitCastExpr {{.*}} 'const volatile _Float16 (*)(const _Float16 &)' -//CHECK-NEXT: | | | | | | | | | `-DeclRefExpr {{.*}} 'const volatile _Float16 (const _Float16 &)' lvalue Function {{.*}} 'func1n' 'const volatile _Float16 (const _Float16 &)' -//CHECK-NEXT: | | | | | | | | `-ImplicitCastExpr {{.*}} 'const _Float16' lvalue -//CHECK-NEXT: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16' -//CHECK-NEXT: | | | | | | | `-CallExpr {{.*}} '_Float16' -//CHECK-NEXT: | | | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' -//CHECK-NEXT: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1f' '_Float16 (_Float16)' -//CHECK-NEXT: | | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16' -//CHECK-NEXT: | | | | | | `-CXXMemberCallExpr {{.*}} '_Float16' -//CHECK-NEXT: | | | | | | |-MemberExpr {{.*}} '' .func1c {{.*}} -//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} 'C1' lvalue Var {{.*}} 'c1' 'C1' -//CHECK-NEXT: | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16' -//CHECK-NEXT: | | | | | `-CallExpr {{.*}} '_Float16' -//CHECK-NEXT: | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' -//CHECK-NEXT: | | | | | | `-MemberExpr {{.*}} '_Float16 (_Float16)' lvalue .func2c {{.*}} -//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} 'C1' lvalue Var {{.*}} 'c1' 'C1' -//CHECK-NEXT: | | | | | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16' -//CHECK-NEXT: | | | | `-CallExpr {{.*}} '_Float16':'_Float16' -//CHECK-NEXT: | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' -//CHECK-NEXT: | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t') -//CHECK-NEXT: | | | | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16' -//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | | `-MemberExpr {{.*}} '_Float16' lvalue .mem2 {{.*}} -//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'S1<_Float16>':'S1<_Float16>' lvalue Var {{.*}} 's1' 'S1<_Float16>':'S1<_Float16>' -//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1n' '_Float16' -//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16' - - auto f5l = -1.f16, *f6l = &f2l, f7l = func1t(f3l); -//CHECK: | |-VarDecl {{.*}} f5l '_Float16':'_Float16' cinit -//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16' prefix '-' -//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00 -//CHECK-NEXT: | |-VarDecl {{.*}} f6l '_Float16 *' cinit -//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16 *' prefix '&' -//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16' -//CHECK-NEXT: | `-VarDecl {{.*}} f7l '_Float16':'_Float16' cinit -//CHECK-NEXT: | `-CallExpr {{.*}} '_Float16':'_Float16' -//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' -//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t') -//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16' - - _Float16 f8l = f4l++; -//CHECK: | `-VarDecl {{.*}} f8l '_Float16' cinit -//CHECK-NEXT: | `-UnaryOperator {{.*}} '_Float16' postfix '++' -//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f4l' '_Float16' - - _Float16 arr1l[] = { -1.f16, -0.f16, -11.f16 }; -//CHECK: `-VarDecl {{.*}} arr1l '_Float16 [3]' cinit -//CHECK-NEXT: `-InitListExpr {{.*}} '_Float16 [3]' -//CHECK-NEXT: |-UnaryOperator {{.*}} '_Float16' prefix '-' -//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00 -//CHECK-NEXT: |-UnaryOperator {{.*}} '_Float16' prefix '-' -//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 0.000000e+00 -//CHECK-NEXT: `-UnaryOperator {{.*}} '_Float16' prefix '-' -//CHECK-NEXT: `-FloatingLiteral {{.*}} '_Float16' 1.100000e+01 - - float cvtf = f2n; -//CHECK: `-VarDecl {{.*}} cvtf 'float' cinit -//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'float' -//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16' - - double cvtd = f2n; -//CHECK: `-VarDecl {{.*}} cvtd 'double' cinit -//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'double' -//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16' - - long double cvtld = f2n; -//CHECK: `-VarDecl {{.*}} cvtld 'long double' cinit -//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'long double' -//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16' - - _Float16 f2h = 42.0f; -//CHECK: `-VarDecl {{.*}} f2h '_Float16' cinit -//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: `-FloatingLiteral {{.*}} 'float' 4.200000e+01 - - _Float16 d2h = 42.0; -//CHECK: `-VarDecl {{.*}} d2h '_Float16' cinit -//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: `-FloatingLiteral {{.*}} 'double' 4.200000e+01 - - _Float16 ld2h = 42.0l; -//CHECK: `-VarDecl {{.*}} ld2h '_Float16' cinit -//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' -//CHECK-NEXT: `-FloatingLiteral {{.*}} 'long double' 4.200000e+01 -} +// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s --strict-whitespace +// RUN: %clang_cc1 -std=c++11 -ast-dump -fnative-half-type %s | FileCheck %s --check-prefix=CHECK-NATIVE --strict-whitespace + +/* Various contexts where type _Float16 can appear. */ + +/* Namespace */ +namespace { + _Float16 f1n; + _Float16 f2n = 33.f16; + _Float16 arr1n[10]; + _Float16 arr2n[] = { 1.2, 3.0, 3.e4 }; + const volatile _Float16 func1n(const _Float16 &arg) { + return arg + f2n + arr1n[4] - arr2n[1]; + } +} + +//CHECK: |-NamespaceDecl +//CHECK-NEXT: | |-VarDecl {{.*}} f1n '_Float16' +//CHECK-NEXT: | |-VarDecl {{.*}} f2n '_Float16' cinit +//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 3.300000e+01 +//CHECK-NEXT: | |-VarDecl {{.*}} arr1n '_Float16 [10]' +//CHECK-NEXT: | |-VarDecl {{.*}} arr2n '_Float16 [3]' cinit +//CHECK-NEXT: | | `-InitListExpr {{.*}} '_Float16 [3]' +//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00 +//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00 +//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 3.000000e+04 +//CHECK-NEXT: | `-FunctionDecl {{.*}} func1n 'const volatile _Float16 (const _Float16 &)' + +/* File */ +_Float16 f1f; +_Float16 f2f = 32.4; +_Float16 arr1f[10]; +_Float16 arr2f[] = { -1.2, -3.0, -3.e4 }; +_Float16 func1f(_Float16 arg); + +//CHECK: |-VarDecl {{.*}} f1f '_Float16' +//CHECK-NEXT: |-VarDecl {{.*}} f2f '_Float16' cinit +//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 3.240000e+01 +//CHECK-NEXT: |-VarDecl {{.*}} arr1f '_Float16 [10]' +//CHECK-NEXT: |-VarDecl {{.*}} arr2f '_Float16 [3]' cinit +//CHECK-NEXT: | `-InitListExpr {{.*}} '_Float16 [3]' +//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | `-UnaryOperator {{.*}} 'double' prefix '-' +//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00 +//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | `-UnaryOperator {{.*}} 'double' prefix '-' +//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00 +//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | `-UnaryOperator {{.*}} 'double' prefix '-' +//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 3.000000e+04 +//CHECK-NEXT: |-FunctionDecl {{.*}} func1f '_Float16 (_Float16)' +//CHECK-NEXT: | `-ParmVarDecl {{.*}} arg '_Float16' + + +// Mixing __fp16 and Float16 types: +// The _Float16 type is first converted to __fp16 type and then the operation +// is completed as if both operands were of __fp16 type. + +__fp16 B = -0.1; +auto C = -1.0f16 + B; + +// When we do *not* have native half types, we expect __fp16 to be promoted to +// float, and consequently also _Float16 promotions to float: + +//CHECK: -VarDecl {{.*}} used B '__fp16' cinit +//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__fp16' +//CHECK-NEXT: | `-UnaryOperator {{.*}} 'double' prefix '-' +//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 1.000000e-01 +//CHECK-NEXT: |-VarDecl {{.*}} C 'float':'float' cinit +//CHECK-NEXT: | `-BinaryOperator {{.*}} 'float' '+' +//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'float' +//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16' prefix '-' +//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00 +//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'float' +//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__fp16' +//CHECK-NEXT: | `-DeclRefExpr {{.*}} '__fp16' lvalue Var 0x{{.*}} 'B' '__fp16' + +// When do have native half types, we expect to see promotions to fp16: + +//CHECK-NATIVE: |-VarDecl {{.*}} used B '__fp16' cinit +//CHECK-NATIVE: | `-ImplicitCastExpr {{.*}} '__fp16' +//CHECK-NATIVE: | `-UnaryOperator {{.*}} 'double' prefix '-' +//CHECK-NATIVE: | `-FloatingLiteral {{.*}} 'double' 1.000000e-01 +//CHECK-NATIVE: |-VarDecl {{.*}} C '__fp16':'__fp16' cinit +//CHECK-NATIVE: | `-BinaryOperator {{.*}} '__fp16' '+' +//CHECK-NATIVE: | |-ImplicitCastExpr {{.*}} '__fp16' +//CHECK-NATIVE: | | `-UnaryOperator {{.*}} '_Float16' prefix '-' +//CHECK-NATIVE: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00 +//CHECK-NATIVE: | `-ImplicitCastExpr {{.*}} '__fp16' +//CHECK-NATIVE: | `-DeclRefExpr {{.*}} '__fp16' lvalue Var 0x{{.*}} 'B' '__fp16' + + +/* Class */ + +class C1 { + _Float16 f1c; + static const _Float16 f2c; + volatile _Float16 f3c; +public: + C1(_Float16 arg) : f1c(arg), f3c(arg) { } + _Float16 func1c(_Float16 arg ) { + return f1c + arg; + } + static _Float16 func2c(_Float16 arg) { + return arg * C1::f2c; + } +}; + +//CHECK: |-CXXRecordDecl {{.*}} referenced class C1 definition +//CHECK: | |-CXXRecordDecl {{.*}} implicit referenced class C1 +//CHECK-NEXT: | |-FieldDecl {{.*}} referenced f1c '_Float16' +//CHECK-NEXT: | |-VarDecl {{.*}} used f2c 'const _Float16' static +//CHECK-NEXT: | |-FieldDecl {{.*}} f3c 'volatile _Float16' +//CHECK-NEXT: | |-AccessSpecDecl +//CHECK-NEXT: | |-CXXConstructorDecl {{.*}} used C1 'void (_Float16) +//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16' +//CHECK-NEXT: | | |-CXXCtorInitializer Field {{.*}} 'f1c' '_Float16' +//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16' +//CHECK-NEXT: | | |-CXXCtorInitializer Field {{.*}} 'f3c' 'volatile _Float16' +//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16' +//CHECK-NEXT: | | `-CompoundStmt +//CHECK-NEXT: | |-CXXMethodDecl {{.*}} used func1c '_Float16 (_Float16) +//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16' +//CHECK-NEXT: | | `-CompoundStmt +//CHECK-NEXT: | | `-ReturnStmt +//CHECK-NEXT: | | `-BinaryOperator {{.*}} '_Float16' '+' +//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | | `-MemberExpr {{.*}} '_Float16' lvalue ->f1c 0x{{.*}} +//CHECK-NEXT: | | | `-CXXThisExpr {{.*}} 'class C1 *' this +//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16' +//CHECK-NEXT: | |-CXXMethodDecl {{.*}} used func2c '_Float16 (_Float16)' static +//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16' +//CHECK-NEXT: | | `-CompoundStmt +//CHECK-NEXT: | | `-ReturnStmt +//CHECK-NEXT: | | `-BinaryOperator {{.*}} '_Float16' '*' +//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16' +//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'const _Float16' lvalue Var 0x{{.*}} 'f2c' 'const _Float16' + + +/* Template */ + +template C func1t(C arg) { + return arg * 2.f16; +} + +//CHECK: |-FunctionTemplateDecl {{.*}} func1t +//CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} C +//CHECK-NEXT: | |-FunctionDecl {{.*}} func1t 'C (C)' +//CHECK-NEXT: | | |-ParmVarDecl {{.*}} referenced arg 'C' +//CHECK-NEXT: | | `-CompoundStmt +//CHECK-NEXT: | | `-ReturnStmt +//CHECK-NEXT: | | `-BinaryOperator {{.*}} '' '*' +//CHECK-NEXT: | | |-DeclRefExpr {{.*}} 'C' lvalue ParmVar {{.*}} 'arg' 'C' +//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 2.000000e+00 +//CHECK-NEXT: | `-FunctionDecl {{.*}} used func1t '_Float16 (_Float16)' +//CHECK-NEXT: | |-TemplateArgument type '_Float16' +//CHECK-NEXT: | |-ParmVarDecl {{.*}} used arg '_Float16':'_Float16' +//CHECK-NEXT: | `-CompoundStmt +//CHECK-NEXT: | `-ReturnStmt +//CHECK-NEXT: | `-BinaryOperator {{.*}} '_Float16' '*' +//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16':'_Float16' +//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16':'_Float16' lvalue ParmVar {{.*}} 'arg' '_Float16':'_Float16' +//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 2.000000e+00 + + +template struct S1 { + C mem1; +}; + +//CHECK: |-ClassTemplateDecl {{.*}} S1 +//CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} referenced class depth 0 index 0 C +//CHECK-NEXT: | |-CXXRecordDecl {{.*}} struct S1 definition +//CHECK: | | |-CXXRecordDecl {{.*}} implicit struct S1 +//CHECK-NEXT: | | `-FieldDecl {{.*}} mem1 'C' +//CHECK-NEXT: | `-ClassTemplateSpecialization {{.*}} 'S1' + +template <> struct S1<_Float16> { + _Float16 mem2; +}; + + +/* Local */ + +extern int printf (const char *__restrict __format, ...); + +int main(void) { + _Float16 f1l = 1e3f16; +//CHECK: | `-VarDecl {{.*}} used f1l '_Float16' cinit +//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+03 + + _Float16 f2l = -0.f16; +//CHECK: | `-VarDecl {{.*}} used f2l '_Float16' cinit +//CHECK-NEXT: | `-UnaryOperator {{.*}} '_Float16' prefix '-' +//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 0.000000e+00 + + _Float16 f3l = 1.000976562; +//CHECK: | `-VarDecl {{.*}} used f3l '_Float16' cinit +//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 1.000977e+00 + + C1 c1(f1l); +//CHECK: | `-VarDecl{{.*}} used c1 'class C1' callinit +//CHECK-NEXT: | `-CXXConstructExpr {{.*}} 'class C1' 'void (_Float16) +//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var 0x{{.*}} 'f1l' '_Float16' + + S1<_Float16> s1 = { 132.f16 }; +//CHECK: | `-VarDecl {{.*}} used s1 'S1<_Float16>':'struct S1<_Float16>' cinit +//CHECK-NEXT: | `-InitListExpr {{.*}} 'S1<_Float16>':'struct S1<_Float16>' +//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.320000e+02 + + _Float16 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) + + func1t(f1l) + s1.mem2 - f1n + f2n; +//CHECK: | `-VarDecl {{.*}} used f4l '_Float16' cinit +//CHECK-NEXT: | `-BinaryOperator {{.*}} '_Float16' '+' +//CHECK-NEXT: | |-BinaryOperator {{.*}} '_Float16' '-' +//CHECK-NEXT: | | |-BinaryOperator {{.*}} '_Float16' '+' +//CHECK-NEXT: | | | |-BinaryOperator {{.*}} '_Float16' '+' +//CHECK-NEXT: | | | | |-BinaryOperator {{.*}} '_Float16' '+' +//CHECK-NEXT: | | | | | |-BinaryOperator {{.*}} '_Float16' '+' +//CHECK-NEXT: | | | | | | |-BinaryOperator {{.*}} '_Float16' '+' +//CHECK-NEXT: | | | | | | | |-CallExpr {{.*}} '_Float16' +//CHECK-NEXT: | | | | | | | | |-ImplicitCastExpr {{.*}} 'const volatile _Float16 (*)(const _Float16 &)' +//CHECK-NEXT: | | | | | | | | | `-DeclRefExpr {{.*}} 'const volatile _Float16 (const _Float16 &)' lvalue Function {{.*}} 'func1n' 'const volatile _Float16 (const _Float16 &)' +//CHECK-NEXT: | | | | | | | | `-ImplicitCastExpr {{.*}} 'const _Float16' lvalue +//CHECK-NEXT: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16' +//CHECK-NEXT: | | | | | | | `-CallExpr {{.*}} '_Float16' +//CHECK-NEXT: | | | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' +//CHECK-NEXT: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1f' '_Float16 (_Float16)' +//CHECK-NEXT: | | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16' +//CHECK-NEXT: | | | | | | `-CXXMemberCallExpr {{.*}} '_Float16' +//CHECK-NEXT: | | | | | | |-MemberExpr {{.*}} '' .func1c {{.*}} +//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} 'class C1' lvalue Var {{.*}} 'c1' 'class C1' +//CHECK-NEXT: | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16' +//CHECK-NEXT: | | | | | `-CallExpr {{.*}} '_Float16' +//CHECK-NEXT: | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' +//CHECK-NEXT: | | | | | | `-MemberExpr {{.*}} '_Float16 (_Float16)' lvalue .func2c {{.*}} +//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} 'class C1' lvalue Var {{.*}} 'c1' 'class C1' +//CHECK-NEXT: | | | | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16' +//CHECK-NEXT: | | | | `-CallExpr {{.*}} '_Float16':'_Float16' +//CHECK-NEXT: | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' +//CHECK-NEXT: | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t') +//CHECK-NEXT: | | | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16' +//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | | `-MemberExpr {{.*}} '_Float16' lvalue .mem2 {{.*}} +//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'S1<_Float16>':'struct S1<_Float16>' lvalue Var {{.*}} 's1' 'S1<_Float16>':'struct S1<_Float16>' +//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1n' '_Float16' +//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16' + + auto f5l = -1.f16, *f6l = &f2l, f7l = func1t(f3l); +//CHECK: | |-VarDecl {{.*}} f5l '_Float16':'_Float16' cinit +//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16' prefix '-' +//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00 +//CHECK-NEXT: | |-VarDecl {{.*}} f6l '_Float16 *' cinit +//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16 *' prefix '&' +//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16' +//CHECK-NEXT: | `-VarDecl {{.*}} f7l '_Float16':'_Float16' cinit +//CHECK-NEXT: | `-CallExpr {{.*}} '_Float16':'_Float16' +//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' +//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t') +//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16' + + _Float16 f8l = f4l++; +//CHECK: | `-VarDecl {{.*}} f8l '_Float16' cinit +//CHECK-NEXT: | `-UnaryOperator {{.*}} '_Float16' postfix '++' +//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f4l' '_Float16' + + _Float16 arr1l[] = { -1.f16, -0.f16, -11.f16 }; +//CHECK: `-VarDecl {{.*}} arr1l '_Float16 [3]' cinit +//CHECK-NEXT: `-InitListExpr {{.*}} '_Float16 [3]' +//CHECK-NEXT: |-UnaryOperator {{.*}} '_Float16' prefix '-' +//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00 +//CHECK-NEXT: |-UnaryOperator {{.*}} '_Float16' prefix '-' +//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 0.000000e+00 +//CHECK-NEXT: `-UnaryOperator {{.*}} '_Float16' prefix '-' +//CHECK-NEXT: `-FloatingLiteral {{.*}} '_Float16' 1.100000e+01 + + float cvtf = f2n; +//CHECK: `-VarDecl {{.*}} cvtf 'float' cinit +//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'float' +//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16' + + double cvtd = f2n; +//CHECK: `-VarDecl {{.*}} cvtd 'double' cinit +//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'double' +//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16' + + long double cvtld = f2n; +//CHECK: `-VarDecl {{.*}} cvtld 'long double' cinit +//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'long double' +//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16' + + _Float16 f2h = 42.0f; +//CHECK: `-VarDecl {{.*}} f2h '_Float16' cinit +//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: `-FloatingLiteral {{.*}} 'float' 4.200000e+01 + + _Float16 d2h = 42.0; +//CHECK: `-VarDecl {{.*}} d2h '_Float16' cinit +//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: `-FloatingLiteral {{.*}} 'double' 4.200000e+01 + + _Float16 ld2h = 42.0l; +//CHECK: `-VarDecl {{.*}} ld2h '_Float16' cinit +//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' +//CHECK-NEXT: `-FloatingLiteral {{.*}} 'long double' 4.200000e+01 +} diff --git a/test/Misc/ast-dump-attr.cpp b/test/Misc/ast-dump-attr.cpp index 9e6f257a92..bf942959a8 100644 --- a/test/Misc/ast-dump-attr.cpp +++ b/test/Misc/ast-dump-attr.cpp @@ -1,211 +1,211 @@ -// RUN: %clang_cc1 -triple x86_64-pc-linux -std=c++11 -Wno-deprecated-declarations -ast-dump -ast-dump-filter Test %s | FileCheck --strict-whitespace %s - -int TestLocation -__attribute__((unused)); -// CHECK: VarDecl{{.*}}TestLocation -// CHECK-NEXT: UnusedAttr 0x{{[^ ]*}} - -int TestIndent -__attribute__((unused)); -// CHECK: {{^}}VarDecl{{.*TestIndent[^()]*$}} -// CHECK-NEXT: {{^}}`-UnusedAttr{{[^()]*$}} - -void TestAttributedStmt() { - switch (1) { - case 1: - [[clang::fallthrough]]; - case 2: - ; - } -} -// CHECK: FunctionDecl{{.*}}TestAttributedStmt -// CHECK: AttributedStmt -// CHECK-NEXT: FallThroughAttr -// CHECK-NEXT: NullStmt - -[[clang::warn_unused_result]] int TestCXX11DeclAttr(); -// CHECK: FunctionDecl{{.*}}TestCXX11DeclAttr -// CHECK-NEXT: WarnUnusedResultAttr - -int TestAlignedNull __attribute__((aligned)); -// CHECK: VarDecl{{.*}}TestAlignedNull -// CHECK-NEXT: AlignedAttr {{.*}} aligned -// CHECK-NEXT: <<>> - -int TestAlignedExpr __attribute__((aligned(4))); -// CHECK: VarDecl{{.*}}TestAlignedExpr -// CHECK-NEXT: AlignedAttr {{.*}} aligned -// CHECK-NEXT: IntegerLiteral - -int TestEnum __attribute__((visibility("default"))); -// CHECK: VarDecl{{.*}}TestEnum -// CHECK-NEXT: VisibilityAttr{{.*}} Default - -class __attribute__((lockable)) Mutex { -} mu1, mu2; -int TestExpr __attribute__((guarded_by(mu1))); -// CHECK: VarDecl{{.*}}TestExpr -// CHECK-NEXT: GuardedByAttr -// CHECK-NEXT: DeclRefExpr{{.*}}mu1 - -class Mutex TestVariadicExpr __attribute__((acquired_after(mu1, mu2))); -// CHECK: VarDecl{{.*}}TestVariadicExpr -// CHECK: AcquiredAfterAttr -// CHECK-NEXT: DeclRefExpr{{.*}}mu1 -// CHECK-NEXT: DeclRefExpr{{.*}}mu2 - -void function1(void *) { - int TestFunction __attribute__((cleanup(function1))); -} -// CHECK: VarDecl{{.*}}TestFunction -// CHECK-NEXT: CleanupAttr{{.*}} Function{{.*}}function1 - -void TestIdentifier(void *, int) -__attribute__((pointer_with_type_tag(ident1,1,2))); -// CHECK: FunctionDecl{{.*}}TestIdentifier -// CHECK: ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag ident1 - -void TestBool(void *, int) -__attribute__((pointer_with_type_tag(bool1,1,2))); -// CHECK: FunctionDecl{{.*}}TestBool -// CHECK: ArgumentWithTypeTagAttr{{.*}}pointer_with_type_tag bool1 0 1 IsPointer - -void TestUnsigned(void *, int) -__attribute__((pointer_with_type_tag(unsigned1,1,2))); -// CHECK: FunctionDecl{{.*}}TestUnsigned -// CHECK: ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag unsigned1 0 1 - -void TestInt(void) __attribute__((constructor(123))); -// CHECK: FunctionDecl{{.*}}TestInt -// CHECK-NEXT: ConstructorAttr{{.*}} 123 - -static int TestString __attribute__((alias("alias1"))); -// CHECK: VarDecl{{.*}}TestString -// CHECK-NEXT: AliasAttr{{.*}} "alias1" - -extern struct s1 TestType -__attribute__((type_tag_for_datatype(ident1,int))); -// CHECK: VarDecl{{.*}}TestType -// CHECK-NEXT: TypeTagForDatatypeAttr{{.*}} int - -void TestLabel() { -L: __attribute__((unused)) int i; -// CHECK: LabelStmt{{.*}}'L' -// CHECK: VarDecl{{.*}}i 'int' -// CHECK-NEXT: UnusedAttr{{.*}} - -M: __attribute(()) int j; -// CHECK: LabelStmt {{.*}} 'M' -// CHECK-NEXT: DeclStmt -// CHECK-NEXT: VarDecl {{.*}} j 'int' - -N: __attribute(()) ; -// CHECK: LabelStmt {{.*}} 'N' -// CHECK-NEXT: NullStmt -} - -namespace Test { -extern "C" int printf(const char *format, ...); -// CHECK: FunctionDecl{{.*}}printf -// CHECK-NEXT: ParmVarDecl{{.*}}format{{.*}}'const char *' -// CHECK-NEXT: FormatAttr{{.*}}Implicit printf 1 2 - -alignas(8) extern int x; -extern int x; -// CHECK: VarDecl{{.*}} x 'int' -// CHECK: VarDecl{{.*}} x 'int' -// CHECK-NEXT: AlignedAttr{{.*}} Inherited -} - -int __attribute__((cdecl)) TestOne(void), TestTwo(void); -// CHECK: FunctionDecl{{.*}}TestOne{{.*}}__attribute__((cdecl)) -// CHECK: FunctionDecl{{.*}}TestTwo{{.*}}__attribute__((cdecl)) - -void func() { - auto Test = []() __attribute__((no_thread_safety_analysis)) {}; - // CHECK: CXXMethodDecl{{.*}}operator() 'void () const' - // CHECK: NoThreadSafetyAnalysisAttr - - // Because GNU's noreturn applies to the function type, and this lambda does - // not have a capture list, the call operator and the function pointer - // conversion should both be noreturn, but the method should not contain a - // NoReturnAttr because the attribute applied to the type. - auto Test2 = []() __attribute__((noreturn)) { while(1); }; - // CHECK: CXXMethodDecl{{.*}}operator() 'void () __attribute__((noreturn)) const' - // CHECK-NOT: NoReturnAttr - // CHECK: CXXConversionDecl{{.*}}operator void (*)() __attribute__((noreturn)) -} - -namespace PR20930 { -struct S { - struct { int Test __attribute__((deprecated)); }; - // CHECK: FieldDecl{{.*}}Test 'int' - // CHECK-NEXT: DeprecatedAttr -}; - -void f() { - S s; - s.Test = 1; - // CHECK: IndirectFieldDecl{{.*}}Test 'int' - // CHECK: DeprecatedAttr -} -} - -struct __attribute__((objc_bridge_related(NSParagraphStyle,,))) TestBridgedRef; -// CHECK: CXXRecordDecl{{.*}} struct TestBridgedRef -// CHECK-NEXT: ObjCBridgeRelatedAttr{{.*}} NSParagraphStyle - -void TestExternalSourceSymbolAttr1() -__attribute__((external_source_symbol(language="Swift", defined_in="module", generated_declaration))); -// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr1 -// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" GeneratedDeclaration - -void TestExternalSourceSymbolAttr2() -__attribute__((external_source_symbol(defined_in="module", language="Swift"))); -// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr2 -// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module"{{$}} - -void TestExternalSourceSymbolAttr3() -__attribute__((external_source_symbol(generated_declaration, language="Objective-C++", defined_in="module"))); -// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr3 -// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Objective-C++" "module" GeneratedDeclaration - -void TestExternalSourceSymbolAttr4() -__attribute__((external_source_symbol(defined_in="Some external file.cs", generated_declaration, language="C Sharp"))); -// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr4 -// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "C Sharp" "Some external file.cs" GeneratedDeclaration - -void TestExternalSourceSymbolAttr5() -__attribute__((external_source_symbol(generated_declaration, defined_in="module", language="Swift"))); -// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr5 -// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" GeneratedDeclaration - -namespace TestNoEscape { - void noescapeFunc(int *p0, __attribute__((noescape)) int *p1) {} - // CHECK: `-FunctionDecl{{.*}} noescapeFunc 'void (int *, __attribute__((noescape)) int *)' - // CHECK-NEXT: ParmVarDecl - // CHECK-NEXT: ParmVarDecl - // CHECK-NEXT: NoEscapeAttr -} - -namespace TestSuppress { - [[gsl::suppress("at-namespace")]]; - // CHECK: NamespaceDecl{{.*}} TestSuppress - // CHECK-NEXT: EmptyDecl{{.*}} - // CHECK-NEXT: SuppressAttr{{.*}} at-namespace - [[gsl::suppress("on-decl")]] - void TestSuppressFunction(); - // CHECK: FunctionDecl{{.*}} TestSuppressFunction - // CHECK-NEXT SuppressAttr{{.*}} on-decl - - void f() { - int *i; - - [[gsl::suppress("on-stmt")]] { - // CHECK: AttributedStmt - // CHECK-NEXT: SuppressAttr{{.*}} on-stmt - // CHECK-NEXT: CompoundStmt - i = reinterpret_cast(7); - } - } -} +// RUN: %clang_cc1 -triple x86_64-pc-linux -std=c++11 -Wno-deprecated-declarations -ast-dump -ast-dump-filter Test %s | FileCheck --strict-whitespace %s + +int TestLocation +__attribute__((unused)); +// CHECK: VarDecl{{.*}}TestLocation +// CHECK-NEXT: UnusedAttr 0x{{[^ ]*}} + +int TestIndent +__attribute__((unused)); +// CHECK: {{^}}VarDecl{{.*TestIndent[^()]*$}} +// CHECK-NEXT: {{^}}`-UnusedAttr{{[^()]*$}} + +void TestAttributedStmt() { + switch (1) { + case 1: + [[clang::fallthrough]]; + case 2: + ; + } +} +// CHECK: FunctionDecl{{.*}}TestAttributedStmt +// CHECK: AttributedStmt +// CHECK-NEXT: FallThroughAttr +// CHECK-NEXT: NullStmt + +[[clang::warn_unused_result]] int TestCXX11DeclAttr(); +// CHECK: FunctionDecl{{.*}}TestCXX11DeclAttr +// CHECK-NEXT: WarnUnusedResultAttr + +int TestAlignedNull __attribute__((aligned)); +// CHECK: VarDecl{{.*}}TestAlignedNull +// CHECK-NEXT: AlignedAttr {{.*}} aligned +// CHECK-NEXT: <<>> + +int TestAlignedExpr __attribute__((aligned(4))); +// CHECK: VarDecl{{.*}}TestAlignedExpr +// CHECK-NEXT: AlignedAttr {{.*}} aligned +// CHECK-NEXT: IntegerLiteral + +int TestEnum __attribute__((visibility("default"))); +// CHECK: VarDecl{{.*}}TestEnum +// CHECK-NEXT: VisibilityAttr{{.*}} Default + +class __attribute__((lockable)) Mutex { +} mu1, mu2; +int TestExpr __attribute__((guarded_by(mu1))); +// CHECK: VarDecl{{.*}}TestExpr +// CHECK-NEXT: GuardedByAttr +// CHECK-NEXT: DeclRefExpr{{.*}}mu1 + +class Mutex TestVariadicExpr __attribute__((acquired_after(mu1, mu2))); +// CHECK: VarDecl{{.*}}TestVariadicExpr +// CHECK: AcquiredAfterAttr +// CHECK-NEXT: DeclRefExpr{{.*}}mu1 +// CHECK-NEXT: DeclRefExpr{{.*}}mu2 + +void function1(void *) { + int TestFunction __attribute__((cleanup(function1))); +} +// CHECK: VarDecl{{.*}}TestFunction +// CHECK-NEXT: CleanupAttr{{.*}} Function{{.*}}function1 + +void TestIdentifier(void *, int) +__attribute__((pointer_with_type_tag(ident1,1,2))); +// CHECK: FunctionDecl{{.*}}TestIdentifier +// CHECK: ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag ident1 + +void TestBool(void *, int) +__attribute__((pointer_with_type_tag(bool1,1,2))); +// CHECK: FunctionDecl{{.*}}TestBool +// CHECK: ArgumentWithTypeTagAttr{{.*}}pointer_with_type_tag bool1 0 1 IsPointer + +void TestUnsigned(void *, int) +__attribute__((pointer_with_type_tag(unsigned1,1,2))); +// CHECK: FunctionDecl{{.*}}TestUnsigned +// CHECK: ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag unsigned1 0 1 + +void TestInt(void) __attribute__((constructor(123))); +// CHECK: FunctionDecl{{.*}}TestInt +// CHECK-NEXT: ConstructorAttr{{.*}} 123 + +static int TestString __attribute__((alias("alias1"))); +// CHECK: VarDecl{{.*}}TestString +// CHECK-NEXT: AliasAttr{{.*}} "alias1" + +extern struct s1 TestType +__attribute__((type_tag_for_datatype(ident1,int))); +// CHECK: VarDecl{{.*}}TestType +// CHECK-NEXT: TypeTagForDatatypeAttr{{.*}} int + +void TestLabel() { +L: __attribute__((unused)) int i; +// CHECK: LabelStmt{{.*}}'L' +// CHECK: VarDecl{{.*}}i 'int' +// CHECK-NEXT: UnusedAttr{{.*}} + +M: __attribute(()) int j; +// CHECK: LabelStmt {{.*}} 'M' +// CHECK-NEXT: DeclStmt +// CHECK-NEXT: VarDecl {{.*}} j 'int' + +N: __attribute(()) ; +// CHECK: LabelStmt {{.*}} 'N' +// CHECK-NEXT: NullStmt +} + +namespace Test { +extern "C" int printf(const char *format, ...); +// CHECK: FunctionDecl{{.*}}printf +// CHECK-NEXT: ParmVarDecl{{.*}}format{{.*}}'const char *' +// CHECK-NEXT: FormatAttr{{.*}}Implicit printf 1 2 + +alignas(8) extern int x; +extern int x; +// CHECK: VarDecl{{.*}} x 'int' +// CHECK: VarDecl{{.*}} x 'int' +// CHECK-NEXT: AlignedAttr{{.*}} Inherited +} + +int __attribute__((cdecl)) TestOne(void), TestTwo(void); +// CHECK: FunctionDecl{{.*}}TestOne{{.*}}__attribute__((cdecl)) +// CHECK: FunctionDecl{{.*}}TestTwo{{.*}}__attribute__((cdecl)) + +void func() { + auto Test = []() __attribute__((no_thread_safety_analysis)) {}; + // CHECK: CXXMethodDecl{{.*}}operator() 'void (void) const' + // CHECK: NoThreadSafetyAnalysisAttr + + // Because GNU's noreturn applies to the function type, and this lambda does + // not have a capture list, the call operator and the function pointer + // conversion should both be noreturn, but the method should not contain a + // NoReturnAttr because the attribute applied to the type. + auto Test2 = []() __attribute__((noreturn)) { while(1); }; + // CHECK: CXXMethodDecl{{.*}}operator() 'void (void) __attribute__((noreturn)) const' + // CHECK-NOT: NoReturnAttr + // CHECK: CXXConversionDecl{{.*}}operator void (*)() __attribute__((noreturn)) +} + +namespace PR20930 { +struct S { + struct { int Test __attribute__((deprecated)); }; + // CHECK: FieldDecl{{.*}}Test 'int' + // CHECK-NEXT: DeprecatedAttr +}; + +void f() { + S s; + s.Test = 1; + // CHECK: IndirectFieldDecl{{.*}}Test 'int' + // CHECK: DeprecatedAttr +} +} + +struct __attribute__((objc_bridge_related(NSParagraphStyle,,))) TestBridgedRef; +// CHECK: CXXRecordDecl{{.*}} struct TestBridgedRef +// CHECK-NEXT: ObjCBridgeRelatedAttr{{.*}} NSParagraphStyle + +void TestExternalSourceSymbolAttr1() +__attribute__((external_source_symbol(language="Swift", defined_in="module", generated_declaration))); +// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr1 +// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" GeneratedDeclaration + +void TestExternalSourceSymbolAttr2() +__attribute__((external_source_symbol(defined_in="module", language="Swift"))); +// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr2 +// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module"{{$}} + +void TestExternalSourceSymbolAttr3() +__attribute__((external_source_symbol(generated_declaration, language="Objective-C++", defined_in="module"))); +// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr3 +// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Objective-C++" "module" GeneratedDeclaration + +void TestExternalSourceSymbolAttr4() +__attribute__((external_source_symbol(defined_in="Some external file.cs", generated_declaration, language="C Sharp"))); +// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr4 +// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "C Sharp" "Some external file.cs" GeneratedDeclaration + +void TestExternalSourceSymbolAttr5() +__attribute__((external_source_symbol(generated_declaration, defined_in="module", language="Swift"))); +// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr5 +// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" GeneratedDeclaration + +namespace TestNoEscape { + void noescapeFunc(int *p0, __attribute__((noescape)) int *p1) {} + // CHECK: `-FunctionDecl{{.*}} noescapeFunc 'void (int *, __attribute__((noescape)) int *)' + // CHECK-NEXT: ParmVarDecl + // CHECK-NEXT: ParmVarDecl + // CHECK-NEXT: NoEscapeAttr +} + +namespace TestSuppress { + [[gsl::suppress("at-namespace")]]; + // CHECK: NamespaceDecl{{.*}} TestSuppress + // CHECK-NEXT: EmptyDecl{{.*}} + // CHECK-NEXT: SuppressAttr{{.*}} at-namespace + [[gsl::suppress("on-decl")]] + void TestSuppressFunction(); + // CHECK: FunctionDecl{{.*}} TestSuppressFunction + // CHECK-NEXT SuppressAttr{{.*}} on-decl + + void f() { + int *i; + + [[gsl::suppress("on-stmt")]] { + // CHECK: AttributedStmt + // CHECK-NEXT: SuppressAttr{{.*}} on-stmt + // CHECK-NEXT: CompoundStmt + i = reinterpret_cast(7); + } + } +} diff --git a/test/Misc/ast-dump-color.cpp b/test/Misc/ast-dump-color.cpp index bc01d4932f..631bc05f22 100644 --- a/test/Misc/ast-dump-color.cpp +++ b/test/Misc/ast-dump-color.cpp @@ -43,7 +43,7 @@ struct Invalid { //CHECK: {{^}}[[Blue]]| |-[[RESET]][[Blue]]HTMLEndTagComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:13[[RESET]], [[Yellow]]col:16[[RESET]]> Name="a"{{$}} //CHECK: {{^}}[[Blue]]| |-[[RESET]][[Blue]]TextComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:5:4[[RESET]]> Text=" "{{$}} //CHECK: {{^}}[[Blue]]| `-[[RESET]][[Blue]]HTMLStartTagComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:5[[RESET]], [[Yellow]]col:8[[RESET]]> Name="br" SelfClosing{{$}} -//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]FunctionDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:9:1[[RESET]], [[Yellow]]line:16:1[[RESET]]> [[Yellow]]line:9:6[[RESET]][[CYAN]] TestAttributedStmt[[RESET]] [[Green]]'void (void)'[[RESET]]{{$}} +//CHECK: {{^}}[[Blue]]|-[[RESET]][[GREEN]]FunctionDecl[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:9:1[[RESET]], [[Yellow]]line:16:1[[RESET]]> [[Yellow]]line:9:6[[RESET]][[CYAN]] TestAttributedStmt[[RESET]] [[Green]]'void ()'[[RESET]]{{$}} //CHECK: {{^}}[[Blue]]| |-[[RESET]][[MAGENTA:.\[0;1;35m]]CompoundStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:27[[RESET]], [[Yellow]]line:16:1[[RESET]]>{{$}} //CHECK: {{^}}[[Blue]]| | `-[[RESET]][[MAGENTA]]SwitchStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:10:3[[RESET]], [[Yellow]]line:15:3[[RESET]]>{{$}} //CHECK: {{^}}[[Blue]]| | |-[[RESET]][[Blue:.\[0;34m]]<<>>[[RESET]]{{$}} diff --git a/test/Misc/ast-dump-decl.cpp b/test/Misc/ast-dump-decl.cpp index c689149af0..0df8a5a2b8 100644 --- a/test/Misc/ast-dump-decl.cpp +++ b/test/Misc/ast-dump-decl.cpp @@ -1,539 +1,539 @@ -// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fms-extensions -ast-dump -ast-dump-filter Test %s | FileCheck -strict-whitespace %s - -class testEnumDecl { - enum class TestEnumDeclScoped; - enum TestEnumDeclFixed : int; -}; -// CHECK: EnumDecl{{.*}} class TestEnumDeclScoped 'int' -// CHECK: EnumDecl{{.*}} TestEnumDeclFixed 'int' - -class testFieldDecl { - int TestFieldDeclInit = 0; -}; -// CHECK: FieldDecl{{.*}} TestFieldDeclInit 'int' -// CHECK-NEXT: IntegerLiteral - -namespace testVarDeclNRVO { - class A { }; - A foo() { - A TestVarDeclNRVO; - return TestVarDeclNRVO; - } -} -// CHECK: VarDecl{{.*}} TestVarDeclNRVO 'testVarDeclNRVO::A' nrvo - -void testParmVarDeclInit(int TestParmVarDeclInit = 0); -// CHECK: ParmVarDecl{{.*}} TestParmVarDeclInit 'int' -// CHECK-NEXT: IntegerLiteral{{.*}} - -namespace TestNamespaceDecl { - int i; -} -// CHECK: NamespaceDecl{{.*}} TestNamespaceDecl -// CHECK-NEXT: VarDecl - -namespace TestNamespaceDecl { - int j; -} -// CHECK: NamespaceDecl{{.*}} TestNamespaceDecl -// CHECK-NEXT: original Namespace -// CHECK-NEXT: VarDecl - -inline namespace TestNamespaceDeclInline { -} -// CHECK: NamespaceDecl{{.*}} TestNamespaceDeclInline inline - -namespace testUsingDirectiveDecl { - namespace A { - } -} -namespace TestUsingDirectiveDecl { - using namespace testUsingDirectiveDecl::A; -} -// CHECK: NamespaceDecl{{.*}} TestUsingDirectiveDecl -// CHECK-NEXT: UsingDirectiveDecl{{.*}} Namespace{{.*}} 'A' - -namespace testNamespaceAlias { - namespace A { - } -} -namespace TestNamespaceAlias = testNamespaceAlias::A; -// CHECK: NamespaceAliasDecl{{.*}} TestNamespaceAlias -// CHECK-NEXT: Namespace{{.*}} 'A' - -using TestTypeAliasDecl = int; -// CHECK: TypeAliasDecl{{.*}} TestTypeAliasDecl 'int' - -namespace testTypeAliasTemplateDecl { - template class A; - template using TestTypeAliasTemplateDecl = A; -} -// CHECK: TypeAliasTemplateDecl{{.*}} TestTypeAliasTemplateDecl -// CHECK-NEXT: TemplateTypeParmDecl -// CHECK-NEXT: TypeAliasDecl{{.*}} TestTypeAliasTemplateDecl 'A' - -namespace testCXXRecordDecl { - class TestEmpty {}; -// CHECK: CXXRecordDecl{{.*}} class TestEmpty -// CHECK-NEXT: DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init -// CHECK-NEXT: DefaultConstructor exists trivial constexpr -// CHECK-NEXT: CopyConstructor simple trivial has_const_param -// CHECK-NEXT: MoveConstructor exists simple trivial -// CHECK-NEXT: CopyAssignment trivial has_const_param -// CHECK-NEXT: MoveAssignment exists simple trivial -// CHECK-NEXT: Destructor simple irrelevant trivial - - class A { }; - class B { }; - class TestCXXRecordDecl : virtual A, public B { - int i; - }; -} -// CHECK: CXXRecordDecl{{.*}} class TestCXXRecordDecl -// CHECK-NEXT: DefinitionData{{$}} -// CHECK-NEXT: DefaultConstructor exists non_trivial -// CHECK-NEXT: CopyConstructor simple non_trivial has_const_param -// CHECK-NEXT: MoveConstructor exists simple non_trivial -// CHECK-NEXT: CopyAssignment non_trivial has_const_param -// CHECK-NEXT: MoveAssignment exists simple non_trivial -// CHECK-NEXT: Destructor simple irrelevant trivial -// CHECK-NEXT: virtual private 'testCXXRecordDecl::A' -// CHECK-NEXT: public 'testCXXRecordDecl::B' -// CHECK-NEXT: CXXRecordDecl{{.*}} class TestCXXRecordDecl -// CHECK-NEXT: FieldDecl - -template -class TestCXXRecordDeclPack : public T... { -}; -// CHECK: CXXRecordDecl{{.*}} class TestCXXRecordDeclPack -// CHECK: public 'T'... -// CHECK-NEXT: CXXRecordDecl{{.*}} class TestCXXRecordDeclPack - -thread_local int TestThreadLocalInt; -// CHECK: TestThreadLocalInt {{.*}} tls_dynamic - -class testCXXMethodDecl { - virtual void TestCXXMethodDeclPure() = 0; - void TestCXXMethodDeclDelete() = delete; - void TestCXXMethodDeclThrow() throw(); - void TestCXXMethodDeclThrowType() throw(int); -}; -// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclPure 'void ()' virtual pure -// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclDelete 'void ()' delete -// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclThrow 'void () throw()' -// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclThrowType 'void () throw(int)' - -namespace testCXXConstructorDecl { - class A { }; - class TestCXXConstructorDecl : public A { - int I; - TestCXXConstructorDecl(A &a, int i) : A(a), I(i) { } - TestCXXConstructorDecl(A &a) : TestCXXConstructorDecl(a, 0) { } - }; -} -// CHECK: CXXConstructorDecl{{.*}} TestCXXConstructorDecl 'void {{.*}}' -// CHECK-NEXT: ParmVarDecl{{.*}} a -// CHECK-NEXT: ParmVarDecl{{.*}} i -// CHECK-NEXT: CXXCtorInitializer{{.*}}A -// CHECK-NEXT: Expr -// CHECK: CXXCtorInitializer{{.*}}I -// CHECK-NEXT: Expr -// CHECK: CompoundStmt -// CHECK: CXXConstructorDecl{{.*}} TestCXXConstructorDecl 'void {{.*}}' -// CHECK-NEXT: ParmVarDecl{{.*}} a -// CHECK-NEXT: CXXCtorInitializer{{.*}}TestCXXConstructorDecl -// CHECK-NEXT: CXXConstructExpr{{.*}}TestCXXConstructorDecl - -class TestCXXDestructorDecl { - ~TestCXXDestructorDecl() { } -}; -// CHECK: CXXDestructorDecl{{.*}} ~TestCXXDestructorDecl 'void () noexcept' -// CHECK-NEXT: CompoundStmt - -// Test that the range of a defaulted members is computed correctly. -class TestMemberRanges { -public: - TestMemberRanges() = default; - TestMemberRanges(const TestMemberRanges &Other) = default; - TestMemberRanges(TestMemberRanges &&Other) = default; - ~TestMemberRanges() = default; - TestMemberRanges &operator=(const TestMemberRanges &Other) = default; - TestMemberRanges &operator=(TestMemberRanges &&Other) = default; -}; -void SomeFunction() { - TestMemberRanges A; - TestMemberRanges B(A); - B = A; - A = static_cast(B); - TestMemberRanges C(static_cast(A)); -} -// CHECK: CXXConstructorDecl{{.*}} -// CHECK: CXXConstructorDecl{{.*}} -// CHECK: CXXConstructorDecl{{.*}} -// CHECK: CXXDestructorDecl{{.*}} -// CHECK: CXXMethodDecl{{.*}} -// CHECK: CXXMethodDecl{{.*}} - -class TestCXXConversionDecl { - operator int() { return 0; } -}; -// CHECK: CXXConversionDecl{{.*}} operator int 'int ()' -// CHECK-NEXT: CompoundStmt - -namespace TestStaticAssertDecl { - static_assert(true, "msg"); -} -// CHECK: NamespaceDecl{{.*}} TestStaticAssertDecl -// CHECK-NEXT: StaticAssertDecl{{.*> .*$}} -// CHECK-NEXT: CXXBoolLiteralExpr -// CHECK-NEXT: StringLiteral - -namespace testFunctionTemplateDecl { - class A { }; - class B { }; - class C { }; - class D { }; - template void TestFunctionTemplate(T) { } - - // implicit instantiation - void bar(A a) { TestFunctionTemplate(a); } - - // explicit specialization - template<> void TestFunctionTemplate(B); - - // explicit instantiation declaration - extern template void TestFunctionTemplate(C); - - // explicit instantiation definition - template void TestFunctionTemplate(D); -} -// CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate -// CHECK-NEXT: TemplateTypeParmDecl -// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)' -// CHECK-NEXT: ParmVarDecl{{.*}} 'T' -// CHECK-NEXT: CompoundStmt -// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}A -// CHECK-NEXT: TemplateArgument -// CHECK-NEXT: ParmVarDecl -// CHECK-NEXT: CompoundStmt -// CHECK-NEXT: Function{{.*}} 'TestFunctionTemplate' {{.*}}B -// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}C -// CHECK-NEXT: TemplateArgument -// CHECK-NEXT: ParmVarDecl -// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}D -// CHECK-NEXT: TemplateArgument -// CHECK-NEXT: ParmVarDecl -// CHECK-NEXT: CompoundStmt -// CHECK: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}B -// CHECK-NEXT: TemplateArgument -// CHECK-NEXT: ParmVarDecl - -namespace testClassTemplateDecl { - class A { }; - class B { }; - class C { }; - class D { }; - - template class TestClassTemplate { - public: - TestClassTemplate(); - ~TestClassTemplate(); - int j(); - int i; - }; - - // implicit instantiation - TestClassTemplate a; - - // explicit specialization - template<> class TestClassTemplate { - int j; - }; - - // explicit instantiation declaration - extern template class TestClassTemplate; - - // explicit instantiation definition - template class TestClassTemplate; - - // partial explicit specialization - template class TestClassTemplatePartial { - int i; - }; - template class TestClassTemplatePartial { - int j; - }; -} -// CHECK: ClassTemplateDecl{{.*}} TestClassTemplate -// CHECK-NEXT: TemplateTypeParmDecl -// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate -// CHECK: CXXRecordDecl{{.*}} class TestClassTemplate -// CHECK-NEXT: AccessSpecDecl{{.*}} public -// CHECK-NEXT: CXXConstructorDecl{{.*}} -// CHECK-NEXT: CXXDestructorDecl{{.*}} -// CHECK-NEXT: CXXMethodDecl{{.*}} -// CHECK-NEXT: FieldDecl{{.*}} i -// CHECK-NEXT: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate -// CHECK: TemplateArgument{{.*}}A -// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate -// CHECK-NEXT: AccessSpecDecl{{.*}} public -// CHECK-NEXT: CXXConstructorDecl{{.*}} -// CHECK-NEXT: CXXDestructorDecl{{.*}} -// CHECK-NEXT: CXXMethodDecl{{.*}} -// CHECK-NEXT: FieldDecl{{.*}} i -// CHECK: ClassTemplateSpecialization{{.*}} 'TestClassTemplate' -// CHECK-NEXT: ClassTemplateSpecialization{{.*}} 'TestClassTemplate' -// CHECK-NEXT: ClassTemplateSpecialization{{.*}} 'TestClassTemplate' - -// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate -// CHECK-NEXT: DefinitionData -// CHECK: TemplateArgument{{.*}}B -// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate -// CHECK-NEXT: FieldDecl{{.*}} j - -// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate -// CHECK: TemplateArgument{{.*}}C -// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate -// CHECK-NEXT: AccessSpecDecl{{.*}} public -// CHECK-NEXT: CXXConstructorDecl{{.*}} -// CHECK-NEXT: CXXDestructorDecl{{.*}} -// CHECK-NEXT: CXXMethodDecl{{.*}} -// CHECK-NEXT: FieldDecl{{.*}} i - -// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate -// CHECK: TemplateArgument{{.*}}D -// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate -// CHECK-NEXT: AccessSpecDecl{{.*}} public -// CHECK-NEXT: CXXConstructorDecl{{.*}} -// CHECK-NEXT: CXXDestructorDecl{{.*}} -// CHECK-NEXT: CXXMethodDecl{{.*}} -// CHECK-NEXT: FieldDecl{{.*}} i - -// CHECK: ClassTemplatePartialSpecializationDecl{{.*}} class TestClassTemplatePartial -// CHECK: TemplateArgument -// CHECK-NEXT: TemplateArgument{{.*}}A -// CHECK-NEXT: TemplateTypeParmDecl -// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplatePartial -// CHECK-NEXT: FieldDecl{{.*}} j - -// PR15220 dump instantiation only once -namespace testCanonicalTemplate { - class A {}; - - template void TestFunctionTemplate(T); - template void TestFunctionTemplate(T); - void bar(A a) { TestFunctionTemplate(a); } - // CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate - // CHECK-NEXT: TemplateTypeParmDecl - // CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)' - // CHECK-NEXT: ParmVarDecl{{.*}} 'T' - // CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}A - // CHECK-NEXT: TemplateArgument - // CHECK-NEXT: ParmVarDecl - // CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate - // CHECK-NEXT: TemplateTypeParmDecl - // CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)' - // CHECK-NEXT: ParmVarDecl{{.*}} 'T' - // CHECK-NEXT: Function{{.*}} 'TestFunctionTemplate' - // CHECK-NOT: TemplateArgument - - template class TestClassTemplate { - template friend class TestClassTemplate; - }; - TestClassTemplate a; - // CHECK: ClassTemplateDecl{{.*}} TestClassTemplate - // CHECK-NEXT: TemplateTypeParmDecl - // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate - // CHECK: CXXRecordDecl{{.*}} class TestClassTemplate - // CHECK-NEXT: FriendDecl - // CHECK-NEXT: ClassTemplateDecl{{.*}} TestClassTemplate - // CHECK-NEXT: TemplateTypeParmDecl - // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate - // CHECK-NEXT: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate - // CHECK: TemplateArgument{{.*}}A - // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate -} - -template -class TestClassScopeFunctionSpecialization { - template void foo(U a) { } - template<> void foo(int a) { } -}; -// CHECK: ClassScopeFunctionSpecializationDecl -// CHECK-NEXT: CXXMethod{{.*}} 'foo' 'void (int)' -// CHECK-NEXT: TemplateArgument{{.*}} 'int' - -namespace TestTemplateTypeParmDecl { - template void foo(); -} -// CHECK: NamespaceDecl{{.*}} TestTemplateTypeParmDecl -// CHECK-NEXT: FunctionTemplateDecl -// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename depth 0 index 0 ... T -// CHECK-NEXT: TemplateTypeParmDecl{{.*}} class depth 0 index 1 U -// CHECK-NEXT: TemplateArgument type 'int' - -namespace TestNonTypeTemplateParmDecl { - template void foo(); -} -// CHECK: NamespaceDecl{{.*}} TestNonTypeTemplateParmDecl -// CHECK-NEXT: FunctionTemplateDecl -// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 0 I -// CHECK-NEXT: TemplateArgument expr -// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1 -// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 1 ... J - -namespace TestTemplateTemplateParmDecl { - template class A; - template