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,
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<std::function<void(bool isLastChild)>, 32> Pending;
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; }
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) << "'";
}
}
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(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();
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);
}
while (!DC->isTranslationUnit())
DC = DC->getParent();
ASTContext &Ctx = cast<TranslationUnitDecl>(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);
}
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;
}
-//=======- PaddingChecker.cpp ------------------------------------*- C++ -*-==//\r
-//\r
-// The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This file defines a checker that checks for padding that could be\r
-// removed by re-ordering members.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-#include "ClangSACheckers.h"\r
-#include "clang/AST/CharUnits.h"\r
-#include "clang/AST/DeclTemplate.h"\r
-#include "clang/AST/RecordLayout.h"\r
-#include "clang/AST/RecursiveASTVisitor.h"\r
-#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"\r
-#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"\r
-#include "clang/StaticAnalyzer/Core/Checker.h"\r
-#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"\r
-#include "llvm/ADT/SmallString.h"\r
-#include "llvm/Support/MathExtras.h"\r
-#include "llvm/Support/raw_ostream.h"\r
-#include <numeric>\r
-\r
-using namespace clang;\r
-using namespace ento;\r
-\r
-namespace {\r
-class PaddingChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {\r
-private:\r
- mutable std::unique_ptr<BugType> PaddingBug;\r
- mutable int64_t AllowedPad;\r
- mutable BugReporter *BR;\r
-\r
-public:\r
- void checkASTDecl(const TranslationUnitDecl *TUD, AnalysisManager &MGR,\r
- BugReporter &BRArg) const {\r
- BR = &BRArg;\r
- AllowedPad =\r
- MGR.getAnalyzerOptions().getOptionAsInteger("AllowedPad", 24, this);\r
- assert(AllowedPad >= 0 && "AllowedPad option should be non-negative");\r
-\r
- // The calls to checkAST* from AnalysisConsumer don't\r
- // visit template instantiations or lambda classes. We\r
- // want to visit those, so we make our own RecursiveASTVisitor.\r
- struct LocalVisitor : public RecursiveASTVisitor<LocalVisitor> {\r
- const PaddingChecker *Checker;\r
- bool shouldVisitTemplateInstantiations() const { return true; }\r
- bool shouldVisitImplicitCode() const { return true; }\r
- explicit LocalVisitor(const PaddingChecker *Checker) : Checker(Checker) {}\r
- bool VisitRecordDecl(const RecordDecl *RD) {\r
- Checker->visitRecord(RD);\r
- return true;\r
- }\r
- bool VisitVarDecl(const VarDecl *VD) {\r
- Checker->visitVariable(VD);\r
- return true;\r
- }\r
- // TODO: Visit array new and mallocs for arrays.\r
- };\r
-\r
- LocalVisitor visitor(this);\r
- visitor.TraverseDecl(const_cast<TranslationUnitDecl *>(TUD));\r
- }\r
-\r
- /// \brief Look for records of overly padded types. If padding *\r
- /// PadMultiplier exceeds AllowedPad, then generate a report.\r
- /// PadMultiplier is used to share code with the array padding\r
- /// checker.\r
- void visitRecord(const RecordDecl *RD, uint64_t PadMultiplier = 1) const {\r
- if (shouldSkipDecl(RD))\r
- return;\r
-\r
- auto &ASTContext = RD->getASTContext();\r
- const ASTRecordLayout &RL = ASTContext.getASTRecordLayout(RD);\r
- assert(llvm::isPowerOf2_64(RL.getAlignment().getQuantity()));\r
-\r
- CharUnits BaselinePad = calculateBaselinePad(RD, ASTContext, RL);\r
- if (BaselinePad.isZero())\r
- return;\r
-\r
- CharUnits OptimalPad;\r
- SmallVector<const FieldDecl *, 20> OptimalFieldsOrder;\r
- std::tie(OptimalPad, OptimalFieldsOrder) =\r
- calculateOptimalPad(RD, ASTContext, RL);\r
-\r
- CharUnits DiffPad = PadMultiplier * (BaselinePad - OptimalPad);\r
- if (DiffPad.getQuantity() <= AllowedPad) {\r
- assert(!DiffPad.isNegative() && "DiffPad should not be negative");\r
- // There is not enough excess padding to trigger a warning.\r
- return;\r
- }\r
- reportRecord(RD, BaselinePad, OptimalPad, OptimalFieldsOrder);\r
- }\r
-\r
- /// \brief Look for arrays of overly padded types. If the padding of the\r
- /// array type exceeds AllowedPad, then generate a report.\r
- void visitVariable(const VarDecl *VD) const {\r
- const ArrayType *ArrTy = VD->getType()->getAsArrayTypeUnsafe();\r
- if (ArrTy == nullptr)\r
- return;\r
- uint64_t Elts = 0;\r
- if (const ConstantArrayType *CArrTy = dyn_cast<ConstantArrayType>(ArrTy))\r
- Elts = CArrTy->getSize().getZExtValue();\r
- if (Elts == 0)\r
- return;\r
- const RecordType *RT = ArrTy->getElementType()->getAs<RecordType>();\r
- if (RT == nullptr)\r
- return;\r
-\r
- // TODO: Recurse into the fields and base classes to see if any\r
- // of those have excess padding.\r
- visitRecord(RT->getDecl(), Elts);\r
- }\r
-\r
- bool shouldSkipDecl(const RecordDecl *RD) const {\r
- auto Location = RD->getLocation();\r
- // If the construct doesn't have a source file, then it's not something\r
- // we want to diagnose.\r
- if (!Location.isValid())\r
- return true;\r
- SrcMgr::CharacteristicKind Kind =\r
- BR->getSourceManager().getFileCharacteristic(Location);\r
- // Throw out all records that come from system headers.\r
- if (Kind != SrcMgr::C_User)\r
- return true;\r
-\r
- // Not going to attempt to optimize unions.\r
- if (RD->isUnion())\r
- return true;\r
- // How do you reorder fields if you haven't got any?\r
- if (RD->field_empty())\r
- return true;\r
- if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {\r
- // Tail padding with base classes ends up being very complicated.\r
- // We will skip objects with base classes for now.\r
- if (CXXRD->getNumBases() != 0)\r
- return true;\r
- // Virtual bases are complicated, skipping those for now.\r
- if (CXXRD->getNumVBases() != 0)\r
- return true;\r
- // Can't layout a template, so skip it. We do still layout the\r
- // instantiations though.\r
- if (CXXRD->getTypeForDecl()->isDependentType())\r
- return true;\r
- if (CXXRD->getTypeForDecl()->isInstantiationDependentType())\r
- return true;\r
- }\r
- auto IsTrickyField = [](const FieldDecl *FD) -> bool {\r
- // Bitfield layout is hard.\r
- if (FD->isBitField())\r
- return true;\r
-\r
- // Variable length arrays are tricky too.\r
- QualType Ty = FD->getType();\r
- if (Ty->isIncompleteArrayType())\r
- return true;\r
- return false;\r
- };\r
-\r
- if (std::any_of(RD->field_begin(), RD->field_end(), IsTrickyField))\r
- return true;\r
- return false;\r
- }\r
-\r
- static CharUnits calculateBaselinePad(const RecordDecl *RD,\r
- const ASTContext &ASTContext,\r
- const ASTRecordLayout &RL) {\r
- CharUnits PaddingSum;\r
- CharUnits Offset = ASTContext.toCharUnitsFromBits(RL.getFieldOffset(0));\r
- for (const FieldDecl *FD : RD->fields()) {\r
- // This checker only cares about the padded size of the\r
- // field, and not the data size. If the field is a record\r
- // with tail padding, then we won't put that number in our\r
- // total because reordering fields won't fix that problem.\r
- CharUnits FieldSize = ASTContext.getTypeSizeInChars(FD->getType());\r
- auto FieldOffsetBits = RL.getFieldOffset(FD->getFieldIndex());\r
- CharUnits FieldOffset = ASTContext.toCharUnitsFromBits(FieldOffsetBits);\r
- PaddingSum += (FieldOffset - Offset);\r
- Offset = FieldOffset + FieldSize;\r
- }\r
- PaddingSum += RL.getSize() - Offset;\r
- return PaddingSum;\r
- }\r
-\r
- /// Optimal padding overview:\r
- /// 1. Find a close approximation to where we can place our first field.\r
- /// This will usually be at offset 0.\r
- /// 2. Try to find the best field that can legally be placed at the current\r
- /// offset.\r
- /// a. "Best" is the largest alignment that is legal, but smallest size.\r
- /// This is to account for overly aligned types.\r
- /// 3. If no fields can fit, pad by rounding the current offset up to the\r
- /// smallest alignment requirement of our fields. Measure and track the\r
- // amount of padding added. Go back to 2.\r
- /// 4. Increment the current offset by the size of the chosen field.\r
- /// 5. Remove the chosen field from the set of future possibilities.\r
- /// 6. Go back to 2 if there are still unplaced fields.\r
- /// 7. Add tail padding by rounding the current offset up to the structure\r
- /// alignment. Track the amount of padding added.\r
-\r
- static std::pair<CharUnits, SmallVector<const FieldDecl *, 20>>\r
- calculateOptimalPad(const RecordDecl *RD, const ASTContext &ASTContext,\r
- const ASTRecordLayout &RL) {\r
- struct FieldInfo {\r
- CharUnits Align;\r
- CharUnits Size;\r
- const FieldDecl *Field;\r
- bool operator<(const FieldInfo &RHS) const {\r
- // Order from small alignments to large alignments,\r
- // then large sizes to small sizes.\r
- // then large field indices to small field indices\r
- return std::make_tuple(Align, -Size,\r
- Field ? -static_cast<int>(Field->getFieldIndex())\r
- : 0) <\r
- std::make_tuple(\r
- RHS.Align, -RHS.Size,\r
- RHS.Field ? -static_cast<int>(RHS.Field->getFieldIndex())\r
- : 0);\r
- }\r
- };\r
- SmallVector<FieldInfo, 20> Fields;\r
- auto GatherSizesAndAlignments = [](const FieldDecl *FD) {\r
- FieldInfo RetVal;\r
- RetVal.Field = FD;\r
- auto &Ctx = FD->getASTContext();\r
- std::tie(RetVal.Size, RetVal.Align) =\r
- Ctx.getTypeInfoInChars(FD->getType());\r
- assert(llvm::isPowerOf2_64(RetVal.Align.getQuantity()));\r
- if (auto Max = FD->getMaxAlignment())\r
- RetVal.Align = std::max(Ctx.toCharUnitsFromBits(Max), RetVal.Align);\r
- return RetVal;\r
- };\r
- std::transform(RD->field_begin(), RD->field_end(),\r
- std::back_inserter(Fields), GatherSizesAndAlignments);\r
- std::sort(Fields.begin(), Fields.end());\r
- // This lets us skip over vptrs and non-virtual bases,\r
- // so that we can just worry about the fields in our object.\r
- // Note that this does cause us to miss some cases where we\r
- // could pack more bytes in to a base class's tail padding.\r
- CharUnits NewOffset = ASTContext.toCharUnitsFromBits(RL.getFieldOffset(0));\r
- CharUnits NewPad;\r
- SmallVector<const FieldDecl *, 20> OptimalFieldsOrder;\r
- while (!Fields.empty()) {\r
- unsigned TrailingZeros =\r
- llvm::countTrailingZeros((unsigned long long)NewOffset.getQuantity());\r
- // If NewOffset is zero, then countTrailingZeros will be 64. Shifting\r
- // 64 will overflow our unsigned long long. Shifting 63 will turn\r
- // our long long (and CharUnits internal type) negative. So shift 62.\r
- long long CurAlignmentBits = 1ull << (std::min)(TrailingZeros, 62u);\r
- CharUnits CurAlignment = CharUnits::fromQuantity(CurAlignmentBits);\r
- FieldInfo InsertPoint = {CurAlignment, CharUnits::Zero(), nullptr};\r
- auto CurBegin = Fields.begin();\r
- auto CurEnd = Fields.end();\r
-\r
- // In the typical case, this will find the last element\r
- // of the vector. We won't find a middle element unless\r
- // we started on a poorly aligned address or have an overly\r
- // aligned field.\r
- auto Iter = std::upper_bound(CurBegin, CurEnd, InsertPoint);\r
- if (Iter != CurBegin) {\r
- // We found a field that we can layout with the current alignment.\r
- --Iter;\r
- NewOffset += Iter->Size;\r
- OptimalFieldsOrder.push_back(Iter->Field);\r
- Fields.erase(Iter);\r
- } else {\r
- // We are poorly aligned, and we need to pad in order to layout another\r
- // field. Round up to at least the smallest field alignment that we\r
- // currently have.\r
- CharUnits NextOffset = NewOffset.alignTo(Fields[0].Align);\r
- NewPad += NextOffset - NewOffset;\r
- NewOffset = NextOffset;\r
- }\r
- }\r
- // Calculate tail padding.\r
- CharUnits NewSize = NewOffset.alignTo(RL.getAlignment());\r
- NewPad += NewSize - NewOffset;\r
- return {NewPad, std::move(OptimalFieldsOrder)};\r
- }\r
-\r
- void reportRecord(\r
- const RecordDecl *RD, CharUnits BaselinePad, CharUnits OptimalPad,\r
- const SmallVector<const FieldDecl *, 20> &OptimalFieldsOrder) const {\r
- if (!PaddingBug)\r
- PaddingBug =\r
- llvm::make_unique<BugType>(this, "Excessive Padding", "Performance");\r
-\r
- SmallString<100> Buf;\r
- llvm::raw_svector_ostream Os(Buf);\r
- Os << "Excessive padding in '";\r
- Os << QualType::getAsString(RD->getTypeForDecl(), Qualifiers(),\r
- LangOptions())\r
- << "'";\r
-\r
- if (auto *TSD = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {\r
- // TODO: make this show up better in the console output and in\r
- // the HTML. Maybe just make it show up in HTML like the path\r
- // diagnostics show.\r
- SourceLocation ILoc = TSD->getPointOfInstantiation();\r
- if (ILoc.isValid())\r
- Os << " instantiated here: "\r
- << ILoc.printToString(BR->getSourceManager());\r
- }\r
-\r
- Os << " (" << BaselinePad.getQuantity() << " padding bytes, where "\r
- << OptimalPad.getQuantity() << " is optimal). \n"\r
- << "Optimal fields order: \n";\r
- for (const auto *FD : OptimalFieldsOrder)\r
- Os << FD->getName() << ", \n";\r
- Os << "consider reordering the fields or adding explicit padding "\r
- "members.";\r
-\r
- PathDiagnosticLocation CELoc =\r
- PathDiagnosticLocation::create(RD, BR->getSourceManager());\r
- auto Report = llvm::make_unique<BugReport>(*PaddingBug, Os.str(), CELoc);\r
- Report->setDeclWithIssue(RD);\r
- Report->addRange(RD->getSourceRange());\r
- BR->emitReport(std::move(Report));\r
- }\r
-};\r
-}\r
-\r
-void ento::registerPaddingChecker(CheckerManager &Mgr) {\r
- Mgr.registerChecker<PaddingChecker>();\r
-}\r
+//=======- 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 <numeric>
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class PaddingChecker : public Checker<check::ASTDecl<TranslationUnitDecl>> {
+private:
+ mutable std::unique_ptr<BugType> 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<LocalVisitor> {
+ 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<TranslationUnitDecl *>(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<const FieldDecl *, 20> 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<ConstantArrayType>(ArrTy))
+ Elts = CArrTy->getSize().getZExtValue();
+ if (Elts == 0)
+ return;
+ const RecordType *RT = ArrTy->getElementType()->getAs<RecordType>();
+ 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<CXXRecordDecl>(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<CharUnits, SmallVector<const FieldDecl *, 20>>
+ 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<int>(Field->getFieldIndex())
+ : 0) <
+ std::make_tuple(
+ RHS.Align, -RHS.Size,
+ RHS.Field ? -static_cast<int>(RHS.Field->getFieldIndex())
+ : 0);
+ }
+ };
+ SmallVector<FieldInfo, 20> 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<const FieldDecl *, 20> 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<const FieldDecl *, 20> &OptimalFieldsOrder) const {
+ if (!PaddingBug)
+ PaddingBug =
+ llvm::make_unique<BugType>(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<ClassTemplateSpecializationDecl>(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<BugReport>(*PaddingBug, Os.str(), CELoc);
+ Report->setDeclWithIssue(RD);
+ Report->addRange(RD->getSourceRange());
+ BR->emitReport(std::move(Report));
+ }
+};
+}
+
+void ento::registerPaddingChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<PaddingChecker>();
+}
-// RUN: %clang_cc1 -ast-dump %s 2>&1 | FileCheck %s\r
-\r
-// CHECK-LABEL: example0\r
-void example0() {\r
- double d = 2.0;\r
- // CHECK: VarDecl{{.*}}rd 'double &'\r
- // CHECK-NEXT: DeclRefExpr\r
- double &rd = d;\r
- // CHECK: VarDecl{{.*}}rcd 'const double &'\r
- // CHECK-NEXT: ImplicitCastExpr{{.*}}'const double' lvalue <NoOp>\r
- const double &rcd = d;\r
-}\r
-\r
-struct A { };\r
-struct B : A { } b;\r
-\r
-// CHECK-LABEL: example1\r
-void example1() {\r
- // CHECK: VarDecl{{.*}}ra 'A &'\r
- // CHECK: ImplicitCastExpr{{.*}}'A' lvalue <DerivedToBase (A)>\r
- A &ra = b;\r
- // CHECK: VarDecl{{.*}}rca 'const A &'\r
- // CHECK: ImplicitCastExpr{{.*}}'const A' lvalue <DerivedToBase (A)>\r
- // CHECK-NOT: MaterializeTemporaryExpr\r
- // CHECK: ImplicitCastExpr{{.*}}'const B' lvalue <NoOp>\r
- const A& rca = b;\r
-}\r
-\r
-extern B f();\r
-\r
-struct X {\r
- operator B();\r
-} x;\r
-\r
-// CHECK-LABEL: example2\r
-void example2() {\r
- // CHECK: VarDecl{{.*}}rca 'const A &'\r
- // CHECK: ImplicitCastExpr{{.*}}'const A' lvalue <DerivedToBase (A)>\r
- // CHECK: MaterializeTemporaryExpr{{.*}}'const B'\r
- // CHECK: ImplicitCastExpr{{.*}}'const B' <NoOp>\r
- // CHECK: CallExpr{{.*}}B\r
- const A &rca = f();\r
- // CHECK: VarDecl{{.*}}r 'const A &'\r
- // CHECK: ImplicitCastExpr{{.*}}'const A' lvalue <DerivedToBase (A)>\r
- // CHECK: MaterializeTemporaryExpr{{.*}}'const B'\r
- // CHECK: ImplicitCastExpr{{.*}}'const B' <NoOp>\r
- // CHECK: CXXMemberCallExpr{{.*}}'B'\r
- const A& r = x;\r
-}\r
-\r
-// CHECK-LABEL: example3\r
-void example3() {\r
- // CHECK: VarDecl{{.*}}rcd2 'const double &'\r
- // CHECK: ImplicitCastExpr{{.*}} <IntegralToFloating>\r
- const double& rcd2 = 2;\r
-}\r
+// 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 <NoOp>
+ 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 <DerivedToBase (A)>
+ A &ra = b;
+ // CHECK: VarDecl{{.*}}rca 'const struct A &'
+ // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <DerivedToBase (A)>
+ // CHECK-NOT: MaterializeTemporaryExpr
+ // CHECK: ImplicitCastExpr{{.*}}'const struct B' lvalue <NoOp>
+ 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 <DerivedToBase (A)>
+ // CHECK: MaterializeTemporaryExpr{{.*}}'const struct B'
+ // CHECK: ImplicitCastExpr{{.*}}'const struct B' <NoOp>
+ // CHECK: CallExpr{{.*}}B
+ const A &rca = f();
+ // CHECK: VarDecl{{.*}}r 'const struct A &'
+ // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <DerivedToBase (A)>
+ // CHECK: MaterializeTemporaryExpr{{.*}}'const struct B'
+ // CHECK: ImplicitCastExpr{{.*}}'const struct B' <NoOp>
+ // CHECK: CXXMemberCallExpr{{.*}}'struct B'
+ const A& r = x;
+}
+
+// CHECK-LABEL: example3
+void example3() {
+ // CHECK: VarDecl{{.*}}rcd2 'const double &'
+ // CHECK: ImplicitCastExpr{{.*}} <IntegralToFloating>
+ const double& rcd2 = 2;
+}
-// RUN: %clang_cc1 -std=c++11 -ast-dump %s | FileCheck %s --strict-whitespace\r
-// RUN: %clang_cc1 -std=c++11 -ast-dump -fnative-half-type %s | FileCheck %s --check-prefix=CHECK-NATIVE --strict-whitespace\r
-\r
-/* Various contexts where type _Float16 can appear. */\r
-\r
-/* Namespace */\r
-namespace {\r
- _Float16 f1n;\r
- _Float16 f2n = 33.f16;\r
- _Float16 arr1n[10];\r
- _Float16 arr2n[] = { 1.2, 3.0, 3.e4 };\r
- const volatile _Float16 func1n(const _Float16 &arg) {\r
- return arg + f2n + arr1n[4] - arr2n[1];\r
- }\r
-}\r
-\r
-//CHECK: |-NamespaceDecl\r
-//CHECK-NEXT: | |-VarDecl {{.*}} f1n '_Float16'\r
-//CHECK-NEXT: | |-VarDecl {{.*}} f2n '_Float16' cinit\r
-//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 3.300000e+01\r
-//CHECK-NEXT: | |-VarDecl {{.*}} arr1n '_Float16 [10]'\r
-//CHECK-NEXT: | |-VarDecl {{.*}} arr2n '_Float16 [3]' cinit\r
-//CHECK-NEXT: | | `-InitListExpr {{.*}} '_Float16 [3]'\r
-//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>\r
-//CHECK-NEXT: | | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00\r
-//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>\r
-//CHECK-NEXT: | | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00\r
-//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>\r
-//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 3.000000e+04\r
-//CHECK-NEXT: | `-FunctionDecl {{.*}} func1n 'const volatile _Float16 (const _Float16 &)'\r
-\r
-/* File */\r
-_Float16 f1f;\r
-_Float16 f2f = 32.4;\r
-_Float16 arr1f[10];\r
-_Float16 arr2f[] = { -1.2, -3.0, -3.e4 };\r
-_Float16 func1f(_Float16 arg);\r
-\r
-//CHECK: |-VarDecl {{.*}} f1f '_Float16'\r
-//CHECK-NEXT: |-VarDecl {{.*}} f2f '_Float16' cinit\r
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>\r
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 3.240000e+01\r
-//CHECK-NEXT: |-VarDecl {{.*}} arr1f '_Float16 [10]'\r
-//CHECK-NEXT: |-VarDecl {{.*}} arr2f '_Float16 [3]' cinit\r
-//CHECK-NEXT: | `-InitListExpr {{.*}} '_Float16 [3]'\r
-//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>\r
-//CHECK-NEXT: | | `-UnaryOperator {{.*}} 'double' prefix '-'\r
-//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00\r
-//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>\r
-//CHECK-NEXT: | | `-UnaryOperator {{.*}} 'double' prefix '-'\r
-//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00\r
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>\r
-//CHECK-NEXT: | `-UnaryOperator {{.*}} 'double' prefix '-'\r
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 3.000000e+04\r
-//CHECK-NEXT: |-FunctionDecl {{.*}} func1f '_Float16 (_Float16)'\r
-//CHECK-NEXT: | `-ParmVarDecl {{.*}} arg '_Float16'\r
-\r
-\r
-// Mixing __fp16 and Float16 types:\r
-// The _Float16 type is first converted to __fp16 type and then the operation\r
-// is completed as if both operands were of __fp16 type.\r
-\r
-__fp16 B = -0.1;\r
-auto C = -1.0f16 + B;\r
-\r
-// When we do *not* have native half types, we expect __fp16 to be promoted to\r
-// float, and consequently also _Float16 promotions to float:\r
-\r
-//CHECK: -VarDecl {{.*}} used B '__fp16' cinit\r
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__fp16' <FloatingCast>\r
-//CHECK-NEXT: | `-UnaryOperator {{.*}} 'double' prefix '-'\r
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 1.000000e-01\r
-//CHECK-NEXT: |-VarDecl {{.*}} C 'float':'float' cinit\r
-//CHECK-NEXT: | `-BinaryOperator {{.*}} 'float' '+'\r
-//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} 'float' <FloatingCast>\r
-//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16' prefix '-'\r
-//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00\r
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'float' <FloatingCast>\r
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__fp16' <LValueToRValue>\r
-//CHECK-NEXT: | `-DeclRefExpr {{.*}} '__fp16' lvalue Var 0x{{.*}} 'B' '__fp16'\r
-\r
-// When do have native half types, we expect to see promotions to fp16:\r
-\r
-//CHECK-NATIVE: |-VarDecl {{.*}} used B '__fp16' cinit\r
-//CHECK-NATIVE: | `-ImplicitCastExpr {{.*}} '__fp16' <FloatingCast>\r
-//CHECK-NATIVE: | `-UnaryOperator {{.*}} 'double' prefix '-'\r
-//CHECK-NATIVE: | `-FloatingLiteral {{.*}} 'double' 1.000000e-01\r
-//CHECK-NATIVE: |-VarDecl {{.*}} C '__fp16':'__fp16' cinit\r
-//CHECK-NATIVE: | `-BinaryOperator {{.*}} '__fp16' '+'\r
-//CHECK-NATIVE: | |-ImplicitCastExpr {{.*}} '__fp16' <FloatingCast>\r
-//CHECK-NATIVE: | | `-UnaryOperator {{.*}} '_Float16' prefix '-'\r
-//CHECK-NATIVE: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00\r
-//CHECK-NATIVE: | `-ImplicitCastExpr {{.*}} '__fp16' <LValueToRValue>\r
-//CHECK-NATIVE: | `-DeclRefExpr {{.*}} '__fp16' lvalue Var 0x{{.*}} 'B' '__fp16'\r
-\r
-\r
-/* Class */\r
-\r
-class C1 {\r
- _Float16 f1c;\r
- static const _Float16 f2c;\r
- volatile _Float16 f3c;\r
-public:\r
- C1(_Float16 arg) : f1c(arg), f3c(arg) { }\r
- _Float16 func1c(_Float16 arg ) {\r
- return f1c + arg;\r
- }\r
- static _Float16 func2c(_Float16 arg) {\r
- return arg * C1::f2c;\r
- }\r
-};\r
-\r
-//CHECK: |-CXXRecordDecl {{.*}} referenced class C1 definition\r
-//CHECK: | |-CXXRecordDecl {{.*}} implicit referenced class C1\r
-//CHECK-NEXT: | |-FieldDecl {{.*}} referenced f1c '_Float16'\r
-//CHECK-NEXT: | |-VarDecl {{.*}} used f2c 'const _Float16' static\r
-//CHECK-NEXT: | |-FieldDecl {{.*}} f3c 'volatile _Float16'\r
-//CHECK-NEXT: | |-AccessSpecDecl\r
-//CHECK-NEXT: | |-CXXConstructorDecl {{.*}} used C1 'void (_Float16)\r
-//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16'\r
-//CHECK-NEXT: | | |-CXXCtorInitializer Field {{.*}} 'f1c' '_Float16'\r
-//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'\r
-//CHECK-NEXT: | | |-CXXCtorInitializer Field {{.*}} 'f3c' 'volatile _Float16'\r
-//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'\r
-//CHECK-NEXT: | | `-CompoundStmt\r
-//CHECK-NEXT: | |-CXXMethodDecl {{.*}} used func1c '_Float16 (_Float16)\r
-//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16'\r
-//CHECK-NEXT: | | `-CompoundStmt\r
-//CHECK-NEXT: | | `-ReturnStmt\r
-//CHECK-NEXT: | | `-BinaryOperator {{.*}} '_Float16' '+'\r
-//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | | | `-MemberExpr {{.*}} '_Float16' lvalue ->f1c 0x{{.*}}\r
-//CHECK-NEXT: | | | `-CXXThisExpr {{.*}} 'C1 *' this\r
-//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'\r
-//CHECK-NEXT: | |-CXXMethodDecl {{.*}} used func2c '_Float16 (_Float16)' static\r
-//CHECK-NEXT: | | |-ParmVarDecl {{.*}} used arg '_Float16'\r
-//CHECK-NEXT: | | `-CompoundStmt\r
-//CHECK-NEXT: | | `-ReturnStmt\r
-//CHECK-NEXT: | | `-BinaryOperator {{.*}} '_Float16' '*'\r
-//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'\r
-//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'const _Float16' lvalue Var 0x{{.*}} 'f2c' 'const _Float16'\r
-\r
-\r
-/* Template */\r
-\r
-template <class C> C func1t(C arg) {\r
- return arg * 2.f16;\r
-}\r
-\r
-//CHECK: |-FunctionTemplateDecl {{.*}} func1t\r
-//CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} C\r
-//CHECK-NEXT: | |-FunctionDecl {{.*}} func1t 'C (C)'\r
-//CHECK-NEXT: | | |-ParmVarDecl {{.*}} referenced arg 'C'\r
-//CHECK-NEXT: | | `-CompoundStmt\r
-//CHECK-NEXT: | | `-ReturnStmt\r
-//CHECK-NEXT: | | `-BinaryOperator {{.*}} '<dependent type>' '*'\r
-//CHECK-NEXT: | | |-DeclRefExpr {{.*}} 'C' lvalue ParmVar {{.*}} 'arg' 'C'\r
-//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 2.000000e+00\r
-//CHECK-NEXT: | `-FunctionDecl {{.*}} used func1t '_Float16 (_Float16)'\r
-//CHECK-NEXT: | |-TemplateArgument type '_Float16'\r
-//CHECK-NEXT: | |-ParmVarDecl {{.*}} used arg '_Float16':'_Float16'\r
-//CHECK-NEXT: | `-CompoundStmt\r
-//CHECK-NEXT: | `-ReturnStmt\r
-//CHECK-NEXT: | `-BinaryOperator {{.*}} '_Float16' '*'\r
-//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16':'_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16':'_Float16' lvalue ParmVar {{.*}} 'arg' '_Float16':'_Float16'\r
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 2.000000e+00\r
-\r
-\r
-template <class C> struct S1 {\r
- C mem1;\r
-};\r
-\r
-//CHECK: |-ClassTemplateDecl {{.*}} S1\r
-//CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} referenced class depth 0 index 0 C\r
-//CHECK-NEXT: | |-CXXRecordDecl {{.*}} struct S1 definition\r
-//CHECK: | | |-CXXRecordDecl {{.*}} implicit struct S1\r
-//CHECK-NEXT: | | `-FieldDecl {{.*}} mem1 'C'\r
-//CHECK-NEXT: | `-ClassTemplateSpecialization {{.*}} 'S1'\r
-\r
-template <> struct S1<_Float16> {\r
- _Float16 mem2;\r
-};\r
-\r
-\r
-/* Local */\r
-\r
-extern int printf (const char *__restrict __format, ...);\r
-\r
-int main(void) {\r
- _Float16 f1l = 1e3f16;\r
-//CHECK: | `-VarDecl {{.*}} used f1l '_Float16' cinit\r
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+03\r
-\r
- _Float16 f2l = -0.f16;\r
-//CHECK: | `-VarDecl {{.*}} used f2l '_Float16' cinit\r
-//CHECK-NEXT: | `-UnaryOperator {{.*}} '_Float16' prefix '-'\r
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 0.000000e+00\r
-\r
- _Float16 f3l = 1.000976562;\r
-//CHECK: | `-VarDecl {{.*}} used f3l '_Float16' cinit\r
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>\r
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} 'double' 1.000977e+00\r
-\r
- C1 c1(f1l);\r
-//CHECK: | `-VarDecl{{.*}} used c1 'C1' callinit\r
-//CHECK-NEXT: | `-CXXConstructExpr {{.*}} 'C1' 'void (_Float16)\r
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var 0x{{.*}} 'f1l' '_Float16'\r
-\r
- S1<_Float16> s1 = { 132.f16 };\r
-//CHECK: | `-VarDecl {{.*}} used s1 'S1<_Float16>':'S1<_Float16>' cinit\r
-//CHECK-NEXT: | `-InitListExpr {{.*}} 'S1<_Float16>':'S1<_Float16>'\r
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.320000e+02\r
-\r
- _Float16 f4l = func1n(f1l) + func1f(f2l) + c1.func1c(f3l) + c1.func2c(f1l) +\r
- func1t(f1l) + s1.mem2 - f1n + f2n;\r
-//CHECK: | `-VarDecl {{.*}} used f4l '_Float16' cinit\r
-//CHECK-NEXT: | `-BinaryOperator {{.*}} '_Float16' '+'\r
-//CHECK-NEXT: | |-BinaryOperator {{.*}} '_Float16' '-'\r
-//CHECK-NEXT: | | |-BinaryOperator {{.*}} '_Float16' '+'\r
-//CHECK-NEXT: | | | |-BinaryOperator {{.*}} '_Float16' '+'\r
-//CHECK-NEXT: | | | | |-BinaryOperator {{.*}} '_Float16' '+'\r
-//CHECK-NEXT: | | | | | |-BinaryOperator {{.*}} '_Float16' '+'\r
-//CHECK-NEXT: | | | | | | |-BinaryOperator {{.*}} '_Float16' '+'\r
-//CHECK-NEXT: | | | | | | | |-CallExpr {{.*}} '_Float16'\r
-//CHECK-NEXT: | | | | | | | | |-ImplicitCastExpr {{.*}} 'const volatile _Float16 (*)(const _Float16 &)' <FunctionToPointerDecay>\r
-//CHECK-NEXT: | | | | | | | | | `-DeclRefExpr {{.*}} 'const volatile _Float16 (const _Float16 &)' lvalue Function {{.*}} 'func1n' 'const volatile _Float16 (const _Float16 &)'\r
-//CHECK-NEXT: | | | | | | | | `-ImplicitCastExpr {{.*}} 'const _Float16' lvalue <NoOp>\r
-//CHECK-NEXT: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'\r
-//CHECK-NEXT: | | | | | | | `-CallExpr {{.*}} '_Float16'\r
-//CHECK-NEXT: | | | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>\r
-//CHECK-NEXT: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1f' '_Float16 (_Float16)'\r
-//CHECK-NEXT: | | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16'\r
-//CHECK-NEXT: | | | | | | `-CXXMemberCallExpr {{.*}} '_Float16'\r
-//CHECK-NEXT: | | | | | | |-MemberExpr {{.*}} '<bound member function type>' .func1c {{.*}}\r
-//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} 'C1' lvalue Var {{.*}} 'c1' 'C1'\r
-//CHECK-NEXT: | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16'\r
-//CHECK-NEXT: | | | | | `-CallExpr {{.*}} '_Float16'\r
-//CHECK-NEXT: | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>\r
-//CHECK-NEXT: | | | | | | `-MemberExpr {{.*}} '_Float16 (_Float16)' lvalue .func2c {{.*}}\r
-//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} 'C1' lvalue Var {{.*}} 'c1' 'C1'\r
-//CHECK-NEXT: | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'\r
-//CHECK-NEXT: | | | | `-CallExpr {{.*}} '_Float16':'_Float16'\r
-//CHECK-NEXT: | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>\r
-//CHECK-NEXT: | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t')\r
-//CHECK-NEXT: | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'\r
-//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | | | `-MemberExpr {{.*}} '_Float16' lvalue .mem2 {{.*}}\r
-//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} 'S1<_Float16>':'S1<_Float16>' lvalue Var {{.*}} 's1' 'S1<_Float16>':'S1<_Float16>'\r
-//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1n' '_Float16'\r
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'\r
-\r
- auto f5l = -1.f16, *f6l = &f2l, f7l = func1t(f3l);\r
-//CHECK: | |-VarDecl {{.*}} f5l '_Float16':'_Float16' cinit\r
-//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16' prefix '-'\r
-//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00\r
-//CHECK-NEXT: | |-VarDecl {{.*}} f6l '_Float16 *' cinit\r
-//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16 *' prefix '&'\r
-//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16'\r
-//CHECK-NEXT: | `-VarDecl {{.*}} f7l '_Float16':'_Float16' cinit\r
-//CHECK-NEXT: | `-CallExpr {{.*}} '_Float16':'_Float16'\r
-//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>\r
-//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t')\r
-//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16'\r
-\r
- _Float16 f8l = f4l++;\r
-//CHECK: | `-VarDecl {{.*}} f8l '_Float16' cinit\r
-//CHECK-NEXT: | `-UnaryOperator {{.*}} '_Float16' postfix '++'\r
-//CHECK-NEXT: | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f4l' '_Float16'\r
-\r
- _Float16 arr1l[] = { -1.f16, -0.f16, -11.f16 };\r
-//CHECK: `-VarDecl {{.*}} arr1l '_Float16 [3]' cinit\r
-//CHECK-NEXT: `-InitListExpr {{.*}} '_Float16 [3]'\r
-//CHECK-NEXT: |-UnaryOperator {{.*}} '_Float16' prefix '-'\r
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00\r
-//CHECK-NEXT: |-UnaryOperator {{.*}} '_Float16' prefix '-'\r
-//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 0.000000e+00\r
-//CHECK-NEXT: `-UnaryOperator {{.*}} '_Float16' prefix '-'\r
-//CHECK-NEXT: `-FloatingLiteral {{.*}} '_Float16' 1.100000e+01\r
-\r
- float cvtf = f2n;\r
-//CHECK: `-VarDecl {{.*}} cvtf 'float' cinit\r
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'float' <FloatingCast>\r
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'\r
-\r
- double cvtd = f2n;\r
-//CHECK: `-VarDecl {{.*}} cvtd 'double' cinit\r
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'double' <FloatingCast>\r
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'\r
-\r
- long double cvtld = f2n;\r
-//CHECK: `-VarDecl {{.*}} cvtld 'long double' cinit\r
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'long double' <FloatingCast>\r
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>\r
-//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'\r
-\r
- _Float16 f2h = 42.0f;\r
-//CHECK: `-VarDecl {{.*}} f2h '_Float16' cinit\r
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>\r
-//CHECK-NEXT: `-FloatingLiteral {{.*}} 'float' 4.200000e+01\r
-\r
- _Float16 d2h = 42.0;\r
-//CHECK: `-VarDecl {{.*}} d2h '_Float16' cinit\r
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>\r
-//CHECK-NEXT: `-FloatingLiteral {{.*}} 'double' 4.200000e+01\r
-\r
- _Float16 ld2h = 42.0l;\r
-//CHECK: `-VarDecl {{.*}} ld2h '_Float16' cinit\r
-//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>\r
-//CHECK-NEXT: `-FloatingLiteral {{.*}} 'long double' 4.200000e+01\r
-}\r
+// 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' <FloatingCast>
+//CHECK-NEXT: | | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00
+//CHECK-NEXT: | | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: | | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00
+//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//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' <FloatingCast>
+//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' <FloatingCast>
+//CHECK-NEXT: | | `-UnaryOperator {{.*}} 'double' prefix '-'
+//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 1.200000e+00
+//CHECK-NEXT: | |-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: | | `-UnaryOperator {{.*}} 'double' prefix '-'
+//CHECK-NEXT: | | `-FloatingLiteral {{.*}} 'double' 3.000000e+00
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//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' <FloatingCast>
+//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' <FloatingCast>
+//CHECK-NEXT: | | `-UnaryOperator {{.*}} '_Float16' prefix '-'
+//CHECK-NEXT: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} 'float' <FloatingCast>
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '__fp16' <LValueToRValue>
+//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' <FloatingCast>
+//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' <FloatingCast>
+//CHECK-NATIVE: | | `-UnaryOperator {{.*}} '_Float16' prefix '-'
+//CHECK-NATIVE: | | `-FloatingLiteral {{.*}} '_Float16' 1.000000e+00
+//CHECK-NATIVE: | `-ImplicitCastExpr {{.*}} '__fp16' <LValueToRValue>
+//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' <LValueToRValue>
+//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'
+//CHECK-NEXT: | | |-CXXCtorInitializer Field {{.*}} 'f3c' 'volatile _Float16'
+//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//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' <LValueToRValue>
+//CHECK-NEXT: | | | `-MemberExpr {{.*}} '_Float16' lvalue ->f1c 0x{{.*}}
+//CHECK-NEXT: | | | `-CXXThisExpr {{.*}} 'class C1 *' this
+//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//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' <LValueToRValue>
+//CHECK-NEXT: | | | `-DeclRefExpr {{.*}} '_Float16' lvalue ParmVar 0x{{.*}} 'arg' '_Float16'
+//CHECK-NEXT: | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | `-DeclRefExpr {{.*}} 'const _Float16' lvalue Var 0x{{.*}} 'f2c' 'const _Float16'
+
+
+/* Template */
+
+template <class C> 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 {{.*}} '<dependent type>' '*'
+//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' <LValueToRValue>
+//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16':'_Float16' lvalue ParmVar {{.*}} 'arg' '_Float16':'_Float16'
+//CHECK-NEXT: | `-FloatingLiteral {{.*}} '_Float16' 2.000000e+00
+
+
+template <class C> 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' <FloatingCast>
+//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' <LValueToRValue>
+//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 &)' <FunctionToPointerDecay>
+//CHECK-NEXT: | | | | | | | | | `-DeclRefExpr {{.*}} 'const volatile _Float16 (const _Float16 &)' lvalue Function {{.*}} 'func1n' 'const volatile _Float16 (const _Float16 &)'
+//CHECK-NEXT: | | | | | | | | `-ImplicitCastExpr {{.*}} 'const _Float16' lvalue <NoOp>
+//CHECK-NEXT: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'
+//CHECK-NEXT: | | | | | | | `-CallExpr {{.*}} '_Float16'
+//CHECK-NEXT: | | | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
+//CHECK-NEXT: | | | | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1f' '_Float16 (_Float16)'
+//CHECK-NEXT: | | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2l' '_Float16'
+//CHECK-NEXT: | | | | | | `-CXXMemberCallExpr {{.*}} '_Float16'
+//CHECK-NEXT: | | | | | | |-MemberExpr {{.*}} '<bound member function type>' .func1c {{.*}}
+//CHECK-NEXT: | | | | | | | `-DeclRefExpr {{.*}} 'class C1' lvalue Var {{.*}} 'c1' 'class C1'
+//CHECK-NEXT: | | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f3l' '_Float16'
+//CHECK-NEXT: | | | | | `-CallExpr {{.*}} '_Float16'
+//CHECK-NEXT: | | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
+//CHECK-NEXT: | | | | | | `-MemberExpr {{.*}} '_Float16 (_Float16)' lvalue .func2c {{.*}}
+//CHECK-NEXT: | | | | | | `-DeclRefExpr {{.*}} 'class C1' lvalue Var {{.*}} 'c1' 'class C1'
+//CHECK-NEXT: | | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'
+//CHECK-NEXT: | | | | `-CallExpr {{.*}} '_Float16':'_Float16'
+//CHECK-NEXT: | | | | |-ImplicitCastExpr {{.*}} '_Float16 (*)(_Float16)' <FunctionToPointerDecay>
+//CHECK-NEXT: | | | | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t')
+//CHECK-NEXT: | | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: | | | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1l' '_Float16'
+//CHECK-NEXT: | | | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//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' <LValueToRValue>
+//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f1n' '_Float16'
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//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)' <FunctionToPointerDecay>
+//CHECK-NEXT: | | `-DeclRefExpr {{.*}} '_Float16 (_Float16)' lvalue Function {{.*}} 'func1t' '_Float16 (_Float16)' (FunctionTemplate {{.*}} 'func1t')
+//CHECK-NEXT: | `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//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' <FloatingCast>
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'
+
+ double cvtd = f2n;
+//CHECK: `-VarDecl {{.*}} cvtd 'double' cinit
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'double' <FloatingCast>
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'
+
+ long double cvtld = f2n;
+//CHECK: `-VarDecl {{.*}} cvtld 'long double' cinit
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'long double' <FloatingCast>
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <LValueToRValue>
+//CHECK-NEXT: `-DeclRefExpr {{.*}} '_Float16' lvalue Var {{.*}} 'f2n' '_Float16'
+
+ _Float16 f2h = 42.0f;
+//CHECK: `-VarDecl {{.*}} f2h '_Float16' cinit
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: `-FloatingLiteral {{.*}} 'float' 4.200000e+01
+
+ _Float16 d2h = 42.0;
+//CHECK: `-VarDecl {{.*}} d2h '_Float16' cinit
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: `-FloatingLiteral {{.*}} 'double' 4.200000e+01
+
+ _Float16 ld2h = 42.0l;
+//CHECK: `-VarDecl {{.*}} ld2h '_Float16' cinit
+//CHECK-NEXT: `-ImplicitCastExpr {{.*}} '_Float16' <FloatingCast>
+//CHECK-NEXT: `-FloatingLiteral {{.*}} 'long double' 4.200000e+01
+}
-// 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\r
-\r
-int TestLocation\r
-__attribute__((unused));\r
-// CHECK: VarDecl{{.*}}TestLocation\r
-// CHECK-NEXT: UnusedAttr 0x{{[^ ]*}} <line:[[@LINE-2]]:16>\r
-\r
-int TestIndent\r
-__attribute__((unused));\r
-// CHECK: {{^}}VarDecl{{.*TestIndent[^()]*$}}\r
-// CHECK-NEXT: {{^}}`-UnusedAttr{{[^()]*$}}\r
-\r
-void TestAttributedStmt() {\r
- switch (1) {\r
- case 1:\r
- [[clang::fallthrough]];\r
- case 2:\r
- ;\r
- }\r
-}\r
-// CHECK: FunctionDecl{{.*}}TestAttributedStmt\r
-// CHECK: AttributedStmt\r
-// CHECK-NEXT: FallThroughAttr\r
-// CHECK-NEXT: NullStmt\r
-\r
-[[clang::warn_unused_result]] int TestCXX11DeclAttr();\r
-// CHECK: FunctionDecl{{.*}}TestCXX11DeclAttr\r
-// CHECK-NEXT: WarnUnusedResultAttr\r
-\r
-int TestAlignedNull __attribute__((aligned));\r
-// CHECK: VarDecl{{.*}}TestAlignedNull\r
-// CHECK-NEXT: AlignedAttr {{.*}} aligned\r
-// CHECK-NEXT: <<<NULL>>>\r
-\r
-int TestAlignedExpr __attribute__((aligned(4)));\r
-// CHECK: VarDecl{{.*}}TestAlignedExpr\r
-// CHECK-NEXT: AlignedAttr {{.*}} aligned\r
-// CHECK-NEXT: IntegerLiteral\r
-\r
-int TestEnum __attribute__((visibility("default")));\r
-// CHECK: VarDecl{{.*}}TestEnum\r
-// CHECK-NEXT: VisibilityAttr{{.*}} Default\r
-\r
-class __attribute__((lockable)) Mutex {\r
-} mu1, mu2;\r
-int TestExpr __attribute__((guarded_by(mu1)));\r
-// CHECK: VarDecl{{.*}}TestExpr\r
-// CHECK-NEXT: GuardedByAttr\r
-// CHECK-NEXT: DeclRefExpr{{.*}}mu1\r
-\r
-class Mutex TestVariadicExpr __attribute__((acquired_after(mu1, mu2)));\r
-// CHECK: VarDecl{{.*}}TestVariadicExpr\r
-// CHECK: AcquiredAfterAttr\r
-// CHECK-NEXT: DeclRefExpr{{.*}}mu1\r
-// CHECK-NEXT: DeclRefExpr{{.*}}mu2\r
-\r
-void function1(void *) {\r
- int TestFunction __attribute__((cleanup(function1)));\r
-}\r
-// CHECK: VarDecl{{.*}}TestFunction\r
-// CHECK-NEXT: CleanupAttr{{.*}} Function{{.*}}function1\r
-\r
-void TestIdentifier(void *, int)\r
-__attribute__((pointer_with_type_tag(ident1,1,2)));\r
-// CHECK: FunctionDecl{{.*}}TestIdentifier\r
-// CHECK: ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag ident1\r
-\r
-void TestBool(void *, int)\r
-__attribute__((pointer_with_type_tag(bool1,1,2)));\r
-// CHECK: FunctionDecl{{.*}}TestBool\r
-// CHECK: ArgumentWithTypeTagAttr{{.*}}pointer_with_type_tag bool1 0 1 IsPointer\r
-\r
-void TestUnsigned(void *, int)\r
-__attribute__((pointer_with_type_tag(unsigned1,1,2)));\r
-// CHECK: FunctionDecl{{.*}}TestUnsigned\r
-// CHECK: ArgumentWithTypeTagAttr{{.*}} pointer_with_type_tag unsigned1 0 1\r
-\r
-void TestInt(void) __attribute__((constructor(123)));\r
-// CHECK: FunctionDecl{{.*}}TestInt\r
-// CHECK-NEXT: ConstructorAttr{{.*}} 123\r
-\r
-static int TestString __attribute__((alias("alias1")));\r
-// CHECK: VarDecl{{.*}}TestString\r
-// CHECK-NEXT: AliasAttr{{.*}} "alias1"\r
-\r
-extern struct s1 TestType\r
-__attribute__((type_tag_for_datatype(ident1,int)));\r
-// CHECK: VarDecl{{.*}}TestType\r
-// CHECK-NEXT: TypeTagForDatatypeAttr{{.*}} int\r
-\r
-void TestLabel() {\r
-L: __attribute__((unused)) int i;\r
-// CHECK: LabelStmt{{.*}}'L'\r
-// CHECK: VarDecl{{.*}}i 'int'\r
-// CHECK-NEXT: UnusedAttr{{.*}}\r
-\r
-M: __attribute(()) int j;\r
-// CHECK: LabelStmt {{.*}} 'M'\r
-// CHECK-NEXT: DeclStmt\r
-// CHECK-NEXT: VarDecl {{.*}} j 'int'\r
-\r
-N: __attribute(()) ;\r
-// CHECK: LabelStmt {{.*}} 'N'\r
-// CHECK-NEXT: NullStmt\r
-}\r
-\r
-namespace Test {\r
-extern "C" int printf(const char *format, ...);\r
-// CHECK: FunctionDecl{{.*}}printf\r
-// CHECK-NEXT: ParmVarDecl{{.*}}format{{.*}}'const char *'\r
-// CHECK-NEXT: FormatAttr{{.*}}Implicit printf 1 2\r
-\r
-alignas(8) extern int x;\r
-extern int x;\r
-// CHECK: VarDecl{{.*}} x 'int'\r
-// CHECK: VarDecl{{.*}} x 'int'\r
-// CHECK-NEXT: AlignedAttr{{.*}} Inherited\r
-}\r
-\r
-int __attribute__((cdecl)) TestOne(void), TestTwo(void);\r
-// CHECK: FunctionDecl{{.*}}TestOne{{.*}}__attribute__((cdecl))\r
-// CHECK: FunctionDecl{{.*}}TestTwo{{.*}}__attribute__((cdecl))\r
-\r
-void func() {\r
- auto Test = []() __attribute__((no_thread_safety_analysis)) {};\r
- // CHECK: CXXMethodDecl{{.*}}operator() 'void () const'\r
- // CHECK: NoThreadSafetyAnalysisAttr\r
-\r
- // Because GNU's noreturn applies to the function type, and this lambda does\r
- // not have a capture list, the call operator and the function pointer\r
- // conversion should both be noreturn, but the method should not contain a\r
- // NoReturnAttr because the attribute applied to the type.\r
- auto Test2 = []() __attribute__((noreturn)) { while(1); };\r
- // CHECK: CXXMethodDecl{{.*}}operator() 'void () __attribute__((noreturn)) const'\r
- // CHECK-NOT: NoReturnAttr\r
- // CHECK: CXXConversionDecl{{.*}}operator void (*)() __attribute__((noreturn))\r
-}\r
-\r
-namespace PR20930 {\r
-struct S {\r
- struct { int Test __attribute__((deprecated)); };\r
- // CHECK: FieldDecl{{.*}}Test 'int'\r
- // CHECK-NEXT: DeprecatedAttr\r
-};\r
-\r
-void f() {\r
- S s;\r
- s.Test = 1;\r
- // CHECK: IndirectFieldDecl{{.*}}Test 'int'\r
- // CHECK: DeprecatedAttr\r
-}\r
-}\r
-\r
-struct __attribute__((objc_bridge_related(NSParagraphStyle,,))) TestBridgedRef;\r
-// CHECK: CXXRecordDecl{{.*}} struct TestBridgedRef\r
-// CHECK-NEXT: ObjCBridgeRelatedAttr{{.*}} NSParagraphStyle\r
-\r
-void TestExternalSourceSymbolAttr1()\r
-__attribute__((external_source_symbol(language="Swift", defined_in="module", generated_declaration)));\r
-// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr1\r
-// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" GeneratedDeclaration\r
-\r
-void TestExternalSourceSymbolAttr2()\r
-__attribute__((external_source_symbol(defined_in="module", language="Swift")));\r
-// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr2\r
-// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module"{{$}}\r
-\r
-void TestExternalSourceSymbolAttr3()\r
-__attribute__((external_source_symbol(generated_declaration, language="Objective-C++", defined_in="module")));\r
-// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr3\r
-// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Objective-C++" "module" GeneratedDeclaration\r
-\r
-void TestExternalSourceSymbolAttr4()\r
-__attribute__((external_source_symbol(defined_in="Some external file.cs", generated_declaration, language="C Sharp")));\r
-// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr4\r
-// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "C Sharp" "Some external file.cs" GeneratedDeclaration\r
-\r
-void TestExternalSourceSymbolAttr5()\r
-__attribute__((external_source_symbol(generated_declaration, defined_in="module", language="Swift")));\r
-// CHECK: FunctionDecl{{.*}} TestExternalSourceSymbolAttr5\r
-// CHECK-NEXT: ExternalSourceSymbolAttr{{.*}} "Swift" "module" GeneratedDeclaration\r
-\r
-namespace TestNoEscape {\r
- void noescapeFunc(int *p0, __attribute__((noescape)) int *p1) {}\r
- // CHECK: `-FunctionDecl{{.*}} noescapeFunc 'void (int *, __attribute__((noescape)) int *)'\r
- // CHECK-NEXT: ParmVarDecl\r
- // CHECK-NEXT: ParmVarDecl\r
- // CHECK-NEXT: NoEscapeAttr\r
-}\r
-\r
-namespace TestSuppress {\r
- [[gsl::suppress("at-namespace")]];\r
- // CHECK: NamespaceDecl{{.*}} TestSuppress\r
- // CHECK-NEXT: EmptyDecl{{.*}}\r
- // CHECK-NEXT: SuppressAttr{{.*}} at-namespace\r
- [[gsl::suppress("on-decl")]]\r
- void TestSuppressFunction();\r
- // CHECK: FunctionDecl{{.*}} TestSuppressFunction\r
- // CHECK-NEXT SuppressAttr{{.*}} on-decl\r
-\r
- void f() {\r
- int *i;\r
-\r
- [[gsl::suppress("on-stmt")]] {\r
- // CHECK: AttributedStmt\r
- // CHECK-NEXT: SuppressAttr{{.*}} on-stmt\r
- // CHECK-NEXT: CompoundStmt\r
- i = reinterpret_cast<int*>(7);\r
- }\r
- }\r
-}\r
+// 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{{[^ ]*}} <line:[[@LINE-2]]:16>
+
+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: <<<NULL>>>
+
+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<int*>(7);
+ }
+ }
+}
//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]]<<<NULL>>>[[RESET]]{{$}}
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fms-extensions -ast-dump -ast-dump-filter Test %s | FileCheck -strict-whitespace %s\r
-\r
-class testEnumDecl {\r
- enum class TestEnumDeclScoped;\r
- enum TestEnumDeclFixed : int;\r
-};\r
-// CHECK: EnumDecl{{.*}} class TestEnumDeclScoped 'int'\r
-// CHECK: EnumDecl{{.*}} TestEnumDeclFixed 'int'\r
-\r
-class testFieldDecl {\r
- int TestFieldDeclInit = 0;\r
-};\r
-// CHECK: FieldDecl{{.*}} TestFieldDeclInit 'int'\r
-// CHECK-NEXT: IntegerLiteral\r
-\r
-namespace testVarDeclNRVO {\r
- class A { };\r
- A foo() {\r
- A TestVarDeclNRVO;\r
- return TestVarDeclNRVO;\r
- }\r
-}\r
-// CHECK: VarDecl{{.*}} TestVarDeclNRVO 'testVarDeclNRVO::A' nrvo\r
-\r
-void testParmVarDeclInit(int TestParmVarDeclInit = 0);\r
-// CHECK: ParmVarDecl{{.*}} TestParmVarDeclInit 'int'\r
-// CHECK-NEXT: IntegerLiteral{{.*}}\r
-\r
-namespace TestNamespaceDecl {\r
- int i;\r
-}\r
-// CHECK: NamespaceDecl{{.*}} TestNamespaceDecl\r
-// CHECK-NEXT: VarDecl\r
-\r
-namespace TestNamespaceDecl {\r
- int j;\r
-}\r
-// CHECK: NamespaceDecl{{.*}} TestNamespaceDecl\r
-// CHECK-NEXT: original Namespace\r
-// CHECK-NEXT: VarDecl\r
-\r
-inline namespace TestNamespaceDeclInline {\r
-}\r
-// CHECK: NamespaceDecl{{.*}} TestNamespaceDeclInline inline\r
-\r
-namespace testUsingDirectiveDecl {\r
- namespace A {\r
- }\r
-}\r
-namespace TestUsingDirectiveDecl {\r
- using namespace testUsingDirectiveDecl::A;\r
-}\r
-// CHECK: NamespaceDecl{{.*}} TestUsingDirectiveDecl\r
-// CHECK-NEXT: UsingDirectiveDecl{{.*}} Namespace{{.*}} 'A'\r
-\r
-namespace testNamespaceAlias {\r
- namespace A {\r
- }\r
-}\r
-namespace TestNamespaceAlias = testNamespaceAlias::A;\r
-// CHECK: NamespaceAliasDecl{{.*}} TestNamespaceAlias\r
-// CHECK-NEXT: Namespace{{.*}} 'A'\r
-\r
-using TestTypeAliasDecl = int;\r
-// CHECK: TypeAliasDecl{{.*}} TestTypeAliasDecl 'int'\r
-\r
-namespace testTypeAliasTemplateDecl {\r
- template<typename T> class A;\r
- template<typename T> using TestTypeAliasTemplateDecl = A<T>;\r
-}\r
-// CHECK: TypeAliasTemplateDecl{{.*}} TestTypeAliasTemplateDecl\r
-// CHECK-NEXT: TemplateTypeParmDecl\r
-// CHECK-NEXT: TypeAliasDecl{{.*}} TestTypeAliasTemplateDecl 'A<T>'\r
-\r
-namespace testCXXRecordDecl {\r
- class TestEmpty {};\r
-// CHECK: CXXRecordDecl{{.*}} class TestEmpty\r
-// 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\r
-// CHECK-NEXT: DefaultConstructor exists trivial constexpr\r
-// CHECK-NEXT: CopyConstructor simple trivial has_const_param\r
-// CHECK-NEXT: MoveConstructor exists simple trivial\r
-// CHECK-NEXT: CopyAssignment trivial has_const_param\r
-// CHECK-NEXT: MoveAssignment exists simple trivial\r
-// CHECK-NEXT: Destructor simple irrelevant trivial\r
-\r
- class A { };\r
- class B { };\r
- class TestCXXRecordDecl : virtual A, public B {\r
- int i;\r
- };\r
-}\r
-// CHECK: CXXRecordDecl{{.*}} class TestCXXRecordDecl\r
-// CHECK-NEXT: DefinitionData{{$}}\r
-// CHECK-NEXT: DefaultConstructor exists non_trivial\r
-// CHECK-NEXT: CopyConstructor simple non_trivial has_const_param\r
-// CHECK-NEXT: MoveConstructor exists simple non_trivial\r
-// CHECK-NEXT: CopyAssignment non_trivial has_const_param\r
-// CHECK-NEXT: MoveAssignment exists simple non_trivial\r
-// CHECK-NEXT: Destructor simple irrelevant trivial\r
-// CHECK-NEXT: virtual private 'testCXXRecordDecl::A'\r
-// CHECK-NEXT: public 'testCXXRecordDecl::B'\r
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestCXXRecordDecl\r
-// CHECK-NEXT: FieldDecl\r
-\r
-template<class...T>\r
-class TestCXXRecordDeclPack : public T... {\r
-};\r
-// CHECK: CXXRecordDecl{{.*}} class TestCXXRecordDeclPack\r
-// CHECK: public 'T'...\r
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestCXXRecordDeclPack\r
-\r
-thread_local int TestThreadLocalInt;\r
-// CHECK: TestThreadLocalInt {{.*}} tls_dynamic\r
-\r
-class testCXXMethodDecl {\r
- virtual void TestCXXMethodDeclPure() = 0;\r
- void TestCXXMethodDeclDelete() = delete;\r
- void TestCXXMethodDeclThrow() throw();\r
- void TestCXXMethodDeclThrowType() throw(int);\r
-};\r
-// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclPure 'void ()' virtual pure\r
-// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclDelete 'void ()' delete\r
-// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclThrow 'void () throw()'\r
-// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclThrowType 'void () throw(int)'\r
-\r
-namespace testCXXConstructorDecl {\r
- class A { };\r
- class TestCXXConstructorDecl : public A {\r
- int I;\r
- TestCXXConstructorDecl(A &a, int i) : A(a), I(i) { }\r
- TestCXXConstructorDecl(A &a) : TestCXXConstructorDecl(a, 0) { }\r
- };\r
-}\r
-// CHECK: CXXConstructorDecl{{.*}} TestCXXConstructorDecl 'void {{.*}}'\r
-// CHECK-NEXT: ParmVarDecl{{.*}} a\r
-// CHECK-NEXT: ParmVarDecl{{.*}} i\r
-// CHECK-NEXT: CXXCtorInitializer{{.*}}A\r
-// CHECK-NEXT: Expr\r
-// CHECK: CXXCtorInitializer{{.*}}I\r
-// CHECK-NEXT: Expr\r
-// CHECK: CompoundStmt\r
-// CHECK: CXXConstructorDecl{{.*}} TestCXXConstructorDecl 'void {{.*}}'\r
-// CHECK-NEXT: ParmVarDecl{{.*}} a\r
-// CHECK-NEXT: CXXCtorInitializer{{.*}}TestCXXConstructorDecl\r
-// CHECK-NEXT: CXXConstructExpr{{.*}}TestCXXConstructorDecl\r
-\r
-class TestCXXDestructorDecl {\r
- ~TestCXXDestructorDecl() { }\r
-};\r
-// CHECK: CXXDestructorDecl{{.*}} ~TestCXXDestructorDecl 'void () noexcept'\r
-// CHECK-NEXT: CompoundStmt\r
-\r
-// Test that the range of a defaulted members is computed correctly.\r
-class TestMemberRanges {\r
-public:\r
- TestMemberRanges() = default;\r
- TestMemberRanges(const TestMemberRanges &Other) = default;\r
- TestMemberRanges(TestMemberRanges &&Other) = default;\r
- ~TestMemberRanges() = default;\r
- TestMemberRanges &operator=(const TestMemberRanges &Other) = default;\r
- TestMemberRanges &operator=(TestMemberRanges &&Other) = default;\r
-};\r
-void SomeFunction() {\r
- TestMemberRanges A;\r
- TestMemberRanges B(A);\r
- B = A;\r
- A = static_cast<TestMemberRanges &&>(B);\r
- TestMemberRanges C(static_cast<TestMemberRanges &&>(A));\r
-}\r
-// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:30>\r
-// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:59>\r
-// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:54>\r
-// CHECK: CXXDestructorDecl{{.*}} <line:{{.*}}:3, col:31>\r
-// CHECK: CXXMethodDecl{{.*}} <line:{{.*}}:3, col:70>\r
-// CHECK: CXXMethodDecl{{.*}} <line:{{.*}}:3, col:65>\r
-\r
-class TestCXXConversionDecl {\r
- operator int() { return 0; }\r
-};\r
-// CHECK: CXXConversionDecl{{.*}} operator int 'int ()'\r
-// CHECK-NEXT: CompoundStmt\r
-\r
-namespace TestStaticAssertDecl {\r
- static_assert(true, "msg");\r
-}\r
-// CHECK: NamespaceDecl{{.*}} TestStaticAssertDecl\r
-// CHECK-NEXT: StaticAssertDecl{{.*> .*$}}\r
-// CHECK-NEXT: CXXBoolLiteralExpr\r
-// CHECK-NEXT: StringLiteral\r
-\r
-namespace testFunctionTemplateDecl {\r
- class A { };\r
- class B { };\r
- class C { };\r
- class D { };\r
- template<typename T> void TestFunctionTemplate(T) { }\r
-\r
- // implicit instantiation\r
- void bar(A a) { TestFunctionTemplate(a); }\r
-\r
- // explicit specialization\r
- template<> void TestFunctionTemplate(B);\r
-\r
- // explicit instantiation declaration\r
- extern template void TestFunctionTemplate(C);\r
-\r
- // explicit instantiation definition\r
- template void TestFunctionTemplate(D);\r
-}\r
-// CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate\r
-// CHECK-NEXT: TemplateTypeParmDecl\r
-// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)'\r
-// CHECK-NEXT: ParmVarDecl{{.*}} 'T'\r
-// CHECK-NEXT: CompoundStmt\r
-// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}A\r
-// CHECK-NEXT: TemplateArgument\r
-// CHECK-NEXT: ParmVarDecl\r
-// CHECK-NEXT: CompoundStmt\r
-// CHECK-NEXT: Function{{.*}} 'TestFunctionTemplate' {{.*}}B\r
-// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}C\r
-// CHECK-NEXT: TemplateArgument\r
-// CHECK-NEXT: ParmVarDecl\r
-// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}D\r
-// CHECK-NEXT: TemplateArgument\r
-// CHECK-NEXT: ParmVarDecl\r
-// CHECK-NEXT: CompoundStmt\r
-// CHECK: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}B\r
-// CHECK-NEXT: TemplateArgument\r
-// CHECK-NEXT: ParmVarDecl\r
-\r
-namespace testClassTemplateDecl {\r
- class A { };\r
- class B { };\r
- class C { };\r
- class D { };\r
-\r
- template<typename T> class TestClassTemplate {\r
- public:\r
- TestClassTemplate();\r
- ~TestClassTemplate();\r
- int j();\r
- int i;\r
- };\r
-\r
- // implicit instantiation\r
- TestClassTemplate<A> a;\r
-\r
- // explicit specialization\r
- template<> class TestClassTemplate<B> {\r
- int j;\r
- };\r
-\r
- // explicit instantiation declaration\r
- extern template class TestClassTemplate<C>;\r
-\r
- // explicit instantiation definition\r
- template class TestClassTemplate<D>;\r
-\r
- // partial explicit specialization\r
- template<typename T1, typename T2> class TestClassTemplatePartial {\r
- int i;\r
- };\r
- template<typename T1> class TestClassTemplatePartial<T1, A> {\r
- int j;\r
- };\r
-}\r
-// CHECK: ClassTemplateDecl{{.*}} TestClassTemplate\r
-// CHECK-NEXT: TemplateTypeParmDecl\r
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate\r
-// CHECK: CXXRecordDecl{{.*}} class TestClassTemplate\r
-// CHECK-NEXT: AccessSpecDecl{{.*}} public\r
-// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>\r
-// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>\r
-// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>\r
-// CHECK-NEXT: FieldDecl{{.*}} i\r
-// CHECK-NEXT: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate\r
-// CHECK: TemplateArgument{{.*}}A\r
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate\r
-// CHECK-NEXT: AccessSpecDecl{{.*}} public\r
-// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>\r
-// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>\r
-// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>\r
-// CHECK-NEXT: FieldDecl{{.*}} i\r
-// CHECK: ClassTemplateSpecialization{{.*}} 'TestClassTemplate'\r
-// CHECK-NEXT: ClassTemplateSpecialization{{.*}} 'TestClassTemplate'\r
-// CHECK-NEXT: ClassTemplateSpecialization{{.*}} 'TestClassTemplate'\r
-\r
-// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate\r
-// CHECK-NEXT: DefinitionData\r
-// CHECK: TemplateArgument{{.*}}B\r
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate\r
-// CHECK-NEXT: FieldDecl{{.*}} j\r
-\r
-// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate\r
-// CHECK: TemplateArgument{{.*}}C\r
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate\r
-// CHECK-NEXT: AccessSpecDecl{{.*}} public\r
-// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>\r
-// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>\r
-// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>\r
-// CHECK-NEXT: FieldDecl{{.*}} i\r
-\r
-// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate\r
-// CHECK: TemplateArgument{{.*}}D\r
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate\r
-// CHECK-NEXT: AccessSpecDecl{{.*}} public\r
-// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>\r
-// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>\r
-// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>\r
-// CHECK-NEXT: FieldDecl{{.*}} i\r
-\r
-// CHECK: ClassTemplatePartialSpecializationDecl{{.*}} class TestClassTemplatePartial\r
-// CHECK: TemplateArgument\r
-// CHECK-NEXT: TemplateArgument{{.*}}A\r
-// CHECK-NEXT: TemplateTypeParmDecl\r
-// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplatePartial\r
-// CHECK-NEXT: FieldDecl{{.*}} j\r
-\r
-// PR15220 dump instantiation only once\r
-namespace testCanonicalTemplate {\r
- class A {};\r
-\r
- template<typename T> void TestFunctionTemplate(T);\r
- template<typename T> void TestFunctionTemplate(T);\r
- void bar(A a) { TestFunctionTemplate(a); }\r
- // CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate\r
- // CHECK-NEXT: TemplateTypeParmDecl\r
- // CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)'\r
- // CHECK-NEXT: ParmVarDecl{{.*}} 'T'\r
- // CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}A\r
- // CHECK-NEXT: TemplateArgument\r
- // CHECK-NEXT: ParmVarDecl\r
- // CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate\r
- // CHECK-NEXT: TemplateTypeParmDecl\r
- // CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)'\r
- // CHECK-NEXT: ParmVarDecl{{.*}} 'T'\r
- // CHECK-NEXT: Function{{.*}} 'TestFunctionTemplate'\r
- // CHECK-NOT: TemplateArgument\r
-\r
- template<typename T1> class TestClassTemplate {\r
- template<typename T2> friend class TestClassTemplate;\r
- };\r
- TestClassTemplate<A> a;\r
- // CHECK: ClassTemplateDecl{{.*}} TestClassTemplate\r
- // CHECK-NEXT: TemplateTypeParmDecl\r
- // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate\r
- // CHECK: CXXRecordDecl{{.*}} class TestClassTemplate\r
- // CHECK-NEXT: FriendDecl\r
- // CHECK-NEXT: ClassTemplateDecl{{.*}} TestClassTemplate\r
- // CHECK-NEXT: TemplateTypeParmDecl\r
- // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate\r
- // CHECK-NEXT: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate\r
- // CHECK: TemplateArgument{{.*}}A\r
- // CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate\r
-}\r
-\r
-template <class T>\r
-class TestClassScopeFunctionSpecialization {\r
- template<class U> void foo(U a) { }\r
- template<> void foo<int>(int a) { }\r
-};\r
-// CHECK: ClassScopeFunctionSpecializationDecl\r
-// CHECK-NEXT: CXXMethod{{.*}} 'foo' 'void (int)'\r
-// CHECK-NEXT: TemplateArgument{{.*}} 'int'\r
-\r
-namespace TestTemplateTypeParmDecl {\r
- template<typename ... T, class U = int> void foo();\r
-}\r
-// CHECK: NamespaceDecl{{.*}} TestTemplateTypeParmDecl\r
-// CHECK-NEXT: FunctionTemplateDecl\r
-// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename depth 0 index 0 ... T\r
-// CHECK-NEXT: TemplateTypeParmDecl{{.*}} class depth 0 index 1 U\r
-// CHECK-NEXT: TemplateArgument type 'int'\r
-\r
-namespace TestNonTypeTemplateParmDecl {\r
- template<int I = 1, int ... J> void foo();\r
-}\r
-// CHECK: NamespaceDecl{{.*}} TestNonTypeTemplateParmDecl\r
-// CHECK-NEXT: FunctionTemplateDecl\r
-// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 0 I\r
-// CHECK-NEXT: TemplateArgument expr\r
-// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1\r
-// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 1 ... J\r
-\r
-namespace TestTemplateTemplateParmDecl {\r
- template<typename T> class A;\r
- template <template <typename> class T = A, template <typename> class ... U> void foo();\r
-}\r
-// CHECK: NamespaceDecl{{.*}} TestTemplateTemplateParmDecl\r
-// CHECK: FunctionTemplateDecl\r
-// CHECK-NEXT: TemplateTemplateParmDecl{{.*}} T\r
-// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename\r
-// CHECK-NEXT: TemplateArgument{{.*}} template A\r
-// CHECK-NEXT: TemplateTemplateParmDecl{{.*}} ... U\r
-// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename\r
-\r
-namespace TestTemplateArgument {\r
- template<typename> class A { };\r
- template<template<typename> class ...> class B { };\r
- int foo();\r
-\r
- template<typename> class testType { };\r
- template class testType<int>;\r
- // CHECK: ClassTemplateSpecializationDecl{{.*}} class testType\r
- // CHECK: TemplateArgument{{.*}} type 'int'\r
-\r
- template<int fp(void)> class testDecl { };\r
- template class testDecl<foo>;\r
- // CHECK: ClassTemplateSpecializationDecl{{.*}} class testDecl\r
- // CHECK: TemplateArgument{{.*}} decl\r
- // CHECK-NEXT: Function{{.*}}foo\r
-\r
- template class testDecl<nullptr>;\r
- // CHECK: ClassTemplateSpecializationDecl{{.*}} class testDecl\r
- // CHECK: TemplateArgument{{.*}} nullptr\r
-\r
- template<int> class testIntegral { };\r
- template class testIntegral<1>;\r
- // CHECK: ClassTemplateSpecializationDecl{{.*}} class testIntegral\r
- // CHECK: TemplateArgument{{.*}} integral 1\r
-\r
- template<template<typename> class> class testTemplate { };\r
- template class testTemplate<A>;\r
- // CHECK: ClassTemplateSpecializationDecl{{.*}} class testTemplate\r
- // CHECK: TemplateArgument{{.*}} A\r
-\r
- template<template<typename> class ...T> class C {\r
- B<T...> testTemplateExpansion;\r
- };\r
- // FIXME: Need TemplateSpecializationType dumping to test TemplateExpansion.\r
-\r
- template<int, int = 0> class testExpr;\r
- template<int I> class testExpr<I> { };\r
- // CHECK: ClassTemplatePartialSpecializationDecl{{.*}} class testExpr\r
- // CHECK: TemplateArgument{{.*}} expr\r
- // CHECK-NEXT: DeclRefExpr{{.*}}I\r
-\r
- template<int, int ...> class testPack { };\r
- template class testPack<0, 1, 2>;\r
- // CHECK: ClassTemplateSpecializationDecl{{.*}} class testPack\r
- // CHECK: TemplateArgument{{.*}} integral 0\r
- // CHECK-NEXT: TemplateArgument{{.*}} pack\r
- // CHECK-NEXT: TemplateArgument{{.*}} integral 1\r
- // CHECK-NEXT: TemplateArgument{{.*}} integral 2\r
-}\r
-\r
-namespace testUsingDecl {\r
- int i;\r
-}\r
-namespace TestUsingDecl {\r
- using testUsingDecl::i;\r
-}\r
-// CHECK: NamespaceDecl{{.*}} TestUsingDecl\r
-// CHECK-NEXT: UsingDecl{{.*}} testUsingDecl::i\r
-// CHECK-NEXT: UsingShadowDecl{{.*}} Var{{.*}} 'i' 'int'\r
-\r
-namespace testUnresolvedUsing {\r
- class A { };\r
- template<class T> class B {\r
- public:\r
- A a;\r
- };\r
- template<class T> class TestUnresolvedUsing : public B<T> {\r
- using typename B<T>::a;\r
- using B<T>::a;\r
- };\r
-}\r
-// CHECK: CXXRecordDecl{{.*}} TestUnresolvedUsing\r
-// CHECK: UnresolvedUsingTypenameDecl{{.*}} B<T>::a\r
-// CHECK: UnresolvedUsingValueDecl{{.*}} B<T>::a\r
-\r
-namespace TestLinkageSpecDecl {\r
- extern "C" void test1();\r
- extern "C++" void test2();\r
-}\r
-// CHECK: NamespaceDecl{{.*}} TestLinkageSpecDecl\r
-// CHECK-NEXT: LinkageSpecDecl{{.*}} C\r
-// CHECK-NEXT: FunctionDecl\r
-// CHECK-NEXT: LinkageSpecDecl{{.*}} C++\r
-// CHECK-NEXT: FunctionDecl\r
-\r
-class TestAccessSpecDecl {\r
-public:\r
-private:\r
-protected:\r
-};\r
-// CHECK: CXXRecordDecl{{.*}} class TestAccessSpecDecl\r
-// CHECK: CXXRecordDecl{{.*}} class TestAccessSpecDecl\r
-// CHECK-NEXT: AccessSpecDecl{{.*}} public\r
-// CHECK-NEXT: AccessSpecDecl{{.*}} private\r
-// CHECK-NEXT: AccessSpecDecl{{.*}} protected\r
-\r
-template<typename T> class TestFriendDecl {\r
- friend int foo();\r
- friend class A;\r
- friend T;\r
-};\r
-// CHECK: CXXRecord{{.*}} TestFriendDecl\r
-// CHECK: CXXRecord{{.*}} TestFriendDecl\r
-// CHECK-NEXT: FriendDecl\r
-// CHECK-NEXT: FunctionDecl{{.*}} foo\r
-// CHECK-NEXT: FriendDecl{{.*}} 'class A':'A'\r
-// CHECK-NEXT: FriendDecl{{.*}} 'T'\r
-\r
-namespace TestFileScopeAsmDecl {\r
- asm("ret");\r
-}\r
-// CHECK: NamespaceDecl{{.*}} TestFileScopeAsmDecl{{$}}\r
-// CHECK: FileScopeAsmDecl{{.*> .*$}}\r
-// CHECK-NEXT: StringLiteral\r
-\r
-namespace TestFriendDecl2 {\r
- void f();\r
- struct S {\r
- friend void f();\r
- };\r
-}\r
-// CHECK: NamespaceDecl [[TestFriendDecl2:0x.*]] <{{.*}}> {{.*}} TestFriendDecl2\r
-// CHECK: |-FunctionDecl [[TestFriendDecl2_f:0x.*]] <{{.*}}> {{.*}} f 'void ()'\r
-// CHECK: `-CXXRecordDecl {{.*}} struct S\r
-// CHECK: |-CXXRecordDecl {{.*}} struct S\r
-// CHECK: `-FriendDecl\r
-// CHECK: `-FunctionDecl {{.*}} parent [[TestFriendDecl2]] prev [[TestFriendDecl2_f]] <{{.*}}> {{.*}} f 'void ()'\r
-\r
-namespace Comment {\r
- extern int Test;\r
- /// Something here.\r
- extern int Test;\r
- extern int Test;\r
-}\r
-\r
-// CHECK: VarDecl {{.*}} Test 'int' extern\r
-// CHECK-NOT: FullComment\r
-// CHECK: VarDecl {{.*}} Test 'int' extern\r
-// CHECK: `-FullComment\r
-// CHECK: `-ParagraphComment\r
-// CHECK: `-TextComment\r
-// CHECK: VarDecl {{.*}} Test 'int' extern\r
-// CHECK-NOT: FullComment\r
+// 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 'class 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<typename T> class A;
+ template<typename T> using TestTypeAliasTemplateDecl = A<T>;
+}
+// CHECK: TypeAliasTemplateDecl{{.*}} TestTypeAliasTemplateDecl
+// CHECK-NEXT: TemplateTypeParmDecl
+// CHECK-NEXT: TypeAliasDecl{{.*}} TestTypeAliasTemplateDecl 'A<T>'
+
+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 'class testCXXRecordDecl::A'
+// CHECK-NEXT: public 'class testCXXRecordDecl::B'
+// CHECK-NEXT: CXXRecordDecl{{.*}} class TestCXXRecordDecl
+// CHECK-NEXT: FieldDecl
+
+template<class...T>
+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 (void)' virtual pure
+// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclDelete 'void (void)' delete
+// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclThrow 'void (void) throw()'
+// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclThrowType 'void (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 (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<TestMemberRanges &&>(B);
+ TestMemberRanges C(static_cast<TestMemberRanges &&>(A));
+}
+// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:30>
+// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:59>
+// CHECK: CXXConstructorDecl{{.*}} <line:{{.*}}:3, col:54>
+// CHECK: CXXDestructorDecl{{.*}} <line:{{.*}}:3, col:31>
+// CHECK: CXXMethodDecl{{.*}} <line:{{.*}}:3, col:70>
+// CHECK: CXXMethodDecl{{.*}} <line:{{.*}}:3, col:65>
+
+class TestCXXConversionDecl {
+ operator int() { return 0; }
+};
+// CHECK: CXXConversionDecl{{.*}} operator int 'int (void)'
+// 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<typename T> 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<typename T> class TestClassTemplate {
+ public:
+ TestClassTemplate();
+ ~TestClassTemplate();
+ int j();
+ int i;
+ };
+
+ // implicit instantiation
+ TestClassTemplate<A> a;
+
+ // explicit specialization
+ template<> class TestClassTemplate<B> {
+ int j;
+ };
+
+ // explicit instantiation declaration
+ extern template class TestClassTemplate<C>;
+
+ // explicit instantiation definition
+ template class TestClassTemplate<D>;
+
+ // partial explicit specialization
+ template<typename T1, typename T2> class TestClassTemplatePartial {
+ int i;
+ };
+ template<typename T1> class TestClassTemplatePartial<T1, A> {
+ int j;
+ };
+}
+// CHECK: ClassTemplateDecl{{.*}} TestClassTemplate
+// CHECK-NEXT: TemplateTypeParmDecl
+// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+// CHECK: CXXRecordDecl{{.*}} class TestClassTemplate
+// CHECK-NEXT: AccessSpecDecl{{.*}} public
+// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
+// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
+// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
+// CHECK-NEXT: FieldDecl{{.*}} i
+// CHECK-NEXT: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
+// CHECK: TemplateArgument{{.*}}A
+// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+// CHECK-NEXT: AccessSpecDecl{{.*}} public
+// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
+// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
+// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
+// 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{{.*}} <line:{{.*}}:5, col:23>
+// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
+// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
+// CHECK-NEXT: FieldDecl{{.*}} i
+
+// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate
+// CHECK: TemplateArgument{{.*}}D
+// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate
+// CHECK-NEXT: AccessSpecDecl{{.*}} public
+// CHECK-NEXT: CXXConstructorDecl{{.*}} <line:{{.*}}:5, col:23>
+// CHECK-NEXT: CXXDestructorDecl{{.*}} <line:{{.*}}:5, col:24>
+// CHECK-NEXT: CXXMethodDecl{{.*}} <line:{{.*}}:5, col:11>
+// 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<typename T> void TestFunctionTemplate(T);
+ template<typename T> 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<typename T1> class TestClassTemplate {
+ template<typename T2> friend class TestClassTemplate;
+ };
+ TestClassTemplate<A> 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 T>
+class TestClassScopeFunctionSpecialization {
+ template<class U> void foo(U a) { }
+ template<> void foo<int>(int a) { }
+};
+// CHECK: ClassScopeFunctionSpecializationDecl
+// CHECK-NEXT: CXXMethod{{.*}} 'foo' 'void (int)'
+// CHECK-NEXT: TemplateArgument{{.*}} 'int'
+
+namespace TestTemplateTypeParmDecl {
+ template<typename ... T, class U = int> 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<int I = 1, int ... J> 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<typename T> class A;
+ template <template <typename> class T = A, template <typename> class ... U> void foo();
+}
+// CHECK: NamespaceDecl{{.*}} TestTemplateTemplateParmDecl
+// CHECK: FunctionTemplateDecl
+// CHECK-NEXT: TemplateTemplateParmDecl{{.*}} T
+// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename
+// CHECK-NEXT: TemplateArgument{{.*}} template A
+// CHECK-NEXT: TemplateTemplateParmDecl{{.*}} ... U
+// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename
+
+namespace TestTemplateArgument {
+ template<typename> class A { };
+ template<template<typename> class ...> class B { };
+ int foo();
+
+ template<typename> class testType { };
+ template class testType<int>;
+ // CHECK: ClassTemplateSpecializationDecl{{.*}} class testType
+ // CHECK: TemplateArgument{{.*}} type 'int'
+
+ template<int fp(void)> class testDecl { };
+ template class testDecl<foo>;
+ // CHECK: ClassTemplateSpecializationDecl{{.*}} class testDecl
+ // CHECK: TemplateArgument{{.*}} decl
+ // CHECK-NEXT: Function{{.*}}foo
+
+ template class testDecl<nullptr>;
+ // CHECK: ClassTemplateSpecializationDecl{{.*}} class testDecl
+ // CHECK: TemplateArgument{{.*}} nullptr
+
+ template<int> class testIntegral { };
+ template class testIntegral<1>;
+ // CHECK: ClassTemplateSpecializationDecl{{.*}} class testIntegral
+ // CHECK: TemplateArgument{{.*}} integral 1
+
+ template<template<typename> class> class testTemplate { };
+ template class testTemplate<A>;
+ // CHECK: ClassTemplateSpecializationDecl{{.*}} class testTemplate
+ // CHECK: TemplateArgument{{.*}} A
+
+ template<template<typename> class ...T> class C {
+ B<T...> testTemplateExpansion;
+ };
+ // FIXME: Need TemplateSpecializationType dumping to test TemplateExpansion.
+
+ template<int, int = 0> class testExpr;
+ template<int I> class testExpr<I> { };
+ // CHECK: ClassTemplatePartialSpecializationDecl{{.*}} class testExpr
+ // CHECK: TemplateArgument{{.*}} expr
+ // CHECK-NEXT: DeclRefExpr{{.*}}I
+
+ template<int, int ...> class testPack { };
+ template class testPack<0, 1, 2>;
+ // CHECK: ClassTemplateSpecializationDecl{{.*}} class testPack
+ // CHECK: TemplateArgument{{.*}} integral 0
+ // CHECK-NEXT: TemplateArgument{{.*}} pack
+ // CHECK-NEXT: TemplateArgument{{.*}} integral 1
+ // CHECK-NEXT: TemplateArgument{{.*}} integral 2
+}
+
+namespace testUsingDecl {
+ int i;
+}
+namespace TestUsingDecl {
+ using testUsingDecl::i;
+}
+// CHECK: NamespaceDecl{{.*}} TestUsingDecl
+// CHECK-NEXT: UsingDecl{{.*}} testUsingDecl::i
+// CHECK-NEXT: UsingShadowDecl{{.*}} Var{{.*}} 'i' 'int'
+
+namespace testUnresolvedUsing {
+ class A { };
+ template<class T> class B {
+ public:
+ A a;
+ };
+ template<class T> class TestUnresolvedUsing : public B<T> {
+ using typename B<T>::a;
+ using B<T>::a;
+ };
+}
+// CHECK: CXXRecordDecl{{.*}} TestUnresolvedUsing
+// CHECK: UnresolvedUsingTypenameDecl{{.*}} B<T>::a
+// CHECK: UnresolvedUsingValueDecl{{.*}} B<T>::a
+
+namespace TestLinkageSpecDecl {
+ extern "C" void test1();
+ extern "C++" void test2();
+}
+// CHECK: NamespaceDecl{{.*}} TestLinkageSpecDecl
+// CHECK-NEXT: LinkageSpecDecl{{.*}} C
+// CHECK-NEXT: FunctionDecl
+// CHECK-NEXT: LinkageSpecDecl{{.*}} C++
+// CHECK-NEXT: FunctionDecl
+
+class TestAccessSpecDecl {
+public:
+private:
+protected:
+};
+// CHECK: CXXRecordDecl{{.*}} class TestAccessSpecDecl
+// CHECK: CXXRecordDecl{{.*}} class TestAccessSpecDecl
+// CHECK-NEXT: AccessSpecDecl{{.*}} public
+// CHECK-NEXT: AccessSpecDecl{{.*}} private
+// CHECK-NEXT: AccessSpecDecl{{.*}} protected
+
+template<typename T> class TestFriendDecl {
+ friend int foo();
+ friend class A;
+ friend T;
+};
+// CHECK: CXXRecord{{.*}} TestFriendDecl
+// CHECK: CXXRecord{{.*}} TestFriendDecl
+// CHECK-NEXT: FriendDecl
+// CHECK-NEXT: FunctionDecl{{.*}} foo
+// CHECK-NEXT: FriendDecl{{.*}} 'class A':'class A'
+// CHECK-NEXT: FriendDecl{{.*}} 'T'
+
+namespace TestFileScopeAsmDecl {
+ asm("ret");
+}
+// CHECK: NamespaceDecl{{.*}} TestFileScopeAsmDecl{{$}}
+// CHECK: FileScopeAsmDecl{{.*> .*$}}
+// CHECK-NEXT: StringLiteral
+
+namespace TestFriendDecl2 {
+ void f();
+ struct S {
+ friend void f();
+ };
+}
+// CHECK: NamespaceDecl [[TestFriendDecl2:0x.*]] <{{.*}}> {{.*}} TestFriendDecl2
+// CHECK: |-FunctionDecl [[TestFriendDecl2_f:0x.*]] <{{.*}}> {{.*}} f 'void (void)'
+// CHECK: `-CXXRecordDecl {{.*}} struct S
+// CHECK: |-CXXRecordDecl {{.*}} struct S
+// CHECK: `-FriendDecl
+// CHECK: `-FunctionDecl {{.*}} parent [[TestFriendDecl2]] prev [[TestFriendDecl2_f]] <{{.*}}> {{.*}} f 'void (void)'
+
+namespace Comment {
+ extern int Test;
+ /// Something here.
+ extern int Test;
+ extern int Test;
+}
+
+// CHECK: VarDecl {{.*}} Test 'int' extern
+// CHECK-NOT: FullComment
+// CHECK: VarDecl {{.*}} Test 'int' extern
+// CHECK: `-FullComment
+// CHECK: `-ParagraphComment
+// CHECK: `-TextComment
+// CHECK: VarDecl {{.*}} Test 'int' extern
+// CHECK-NOT: FullComment
-// RUN: not %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fms-extensions -ast-dump -ast-dump-filter Test %s | FileCheck -check-prefix CHECK -strict-whitespace %s\r
-\r
-namespace TestInvalidRParenOnCXXUnresolvedConstructExpr {\r
-template <class T>\r
-void f(T i, T j) {\r
- return T (i, j;\r
-}\r
-}\r
-\r
-// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidRParenOnCXXUnresolvedConstructExpr\r
-// CHECK-NEXT: `-FunctionTemplateDecl\r
-// CHECK-NEXT: |-TemplateTypeParmDecl\r
-// CHECK-NEXT: `-FunctionDecl\r
-// CHECK-NEXT: |-ParmVarDecl\r
-// CHECK-NEXT: |-ParmVarDecl\r
-// CHECK-NEXT: `-CompoundStmt\r
-// CHECK-NEXT: `-ReturnStmt\r
-// CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} <col:10, col:16> 'T'\r
-// CHECK-NEXT: |-DeclRefExpr {{.*}} <col:13> 'T' lvalue ParmVar {{.*}} 'i' 'T'\r
-// CHECK-NEXT: `-DeclRefExpr {{.*}} <col:16> 'T' lvalue ParmVar {{.*}} 'j' 'T'\r
-\r
-\r
-namespace TestInvalidIf {\r
-int g(int i) {\r
- if (invalid_condition)\r
- return 4;\r
- else\r
- return i;\r
-}\r
-}\r
-// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidIf\r
-// CHECK-NEXT: `-FunctionDecl\r
-// CHECK-NEXT: |-ParmVarDecl\r
-// CHECK-NEXT: `-CompoundStmt\r
-// CHECK-NEXT: `-IfStmt {{.*}} <line:25:3, line:28:12>\r
-// CHECK-NEXT: |-<<<NULL>>>\r
-// CHECK-NEXT: |-<<<NULL>>>\r
-// CHECK-NEXT: |-OpaqueValueExpr {{.*}} <<invalid sloc>> 'bool'\r
-// CHECK-NEXT: |-ReturnStmt {{.*}} <line:26:5, col:12>\r
-// CHECK-NEXT: | `-IntegerLiteral {{.*}} <col:12> 'int' 4\r
-// CHECK-NEXT: `-ReturnStmt {{.*}} <line:28:5, col:12>\r
-// CHECK-NEXT: `-ImplicitCastExpr {{.*}} <col:12> 'int' <LValueToRValue>\r
-// CHECK-NEXT: `-DeclRefExpr {{.*}} <col:12> 'int' lvalue ParmVar {{.*}} 'i' 'int'\r
-\r
-namespace TestInvalidFunctionDecl {\r
-struct Str {\r
- double foo1(double, invalid_type);\r
-};\r
-double Str::foo1(double, invalid_type)\r
-{ return 45; }\r
-}\r
-// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl\r
-// CHECK-NEXT: |-CXXRecordDecl {{.*}} <line:46:1, line:48:1> line:46:8 struct Str definition\r
-// CHECK: | |-CXXRecordDecl {{.*}} <col:1, col:8> col:8 implicit struct Str\r
-// CHECK-NEXT: | `-CXXMethodDecl {{.*}} <line:47:4, col:36> col:11 invalid foo1 'double (double, int)'\r
-// CHECK-NEXT: | |-ParmVarDecl {{.*}} <col:16> col:22 'double'\r
-// CHECK-NEXT: | `-ParmVarDecl {{.*}} <col:24, <invalid sloc>> col:36 invalid 'int'\r
-// CHECK-NEXT: `-CXXMethodDecl {{.*}} parent {{.*}} <line:49:1, line:50:14> line:49:13 invalid foo1 'double (double, int)'\r
-// CHECK-NEXT: |-ParmVarDecl {{.*}} <col:18> col:24 'double'\r
-// CHECK-NEXT: |-ParmVarDecl {{.*}} <col:26, <invalid sloc>> col:38 invalid 'int'\r
-// CHECK-NEXT: `-CompoundStmt {{.*}} <line:50:1, col:14>\r
-// CHECK-NEXT: `-ReturnStmt {{.*}} <col:3, col:10>\r
-// CHECK-NEXT: `-ImplicitCastExpr {{.*}} <col:10> 'double' <IntegralToFloating>\r
-// CHECK-NEXT: `-IntegerLiteral {{.*}} <col:10> 'int' 45\r
+// RUN: not %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -fms-extensions -ast-dump -ast-dump-filter Test %s | FileCheck -check-prefix CHECK -strict-whitespace %s
+
+namespace TestInvalidRParenOnCXXUnresolvedConstructExpr {
+template <class T>
+void f(T i, T j) {
+ return T (i, j;
+}
+}
+
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidRParenOnCXXUnresolvedConstructExpr
+// CHECK-NEXT: `-FunctionTemplateDecl
+// CHECK-NEXT: |-TemplateTypeParmDecl
+// CHECK-NEXT: `-FunctionDecl
+// CHECK-NEXT: |-ParmVarDecl
+// CHECK-NEXT: |-ParmVarDecl
+// CHECK-NEXT: `-CompoundStmt
+// CHECK-NEXT: `-ReturnStmt
+// CHECK-NEXT: `-CXXUnresolvedConstructExpr {{.*}} <col:10, col:16> 'T'
+// CHECK-NEXT: |-DeclRefExpr {{.*}} <col:13> 'T' lvalue ParmVar {{.*}} 'i' 'T'
+// CHECK-NEXT: `-DeclRefExpr {{.*}} <col:16> 'T' lvalue ParmVar {{.*}} 'j' 'T'
+
+
+namespace TestInvalidIf {
+int g(int i) {
+ if (invalid_condition)
+ return 4;
+ else
+ return i;
+}
+}
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidIf
+// CHECK-NEXT: `-FunctionDecl
+// CHECK-NEXT: |-ParmVarDecl
+// CHECK-NEXT: `-CompoundStmt
+// CHECK-NEXT: `-IfStmt {{.*}} <line:25:3, line:28:12>
+// CHECK-NEXT: |-<<<NULL>>>
+// CHECK-NEXT: |-<<<NULL>>>
+// CHECK-NEXT: |-OpaqueValueExpr {{.*}} <<invalid sloc>> '_Bool'
+// CHECK-NEXT: |-ReturnStmt {{.*}} <line:26:5, col:12>
+// CHECK-NEXT: | `-IntegerLiteral {{.*}} <col:12> 'int' 4
+// CHECK-NEXT: `-ReturnStmt {{.*}} <line:28:5, col:12>
+// CHECK-NEXT: `-ImplicitCastExpr {{.*}} <col:12> 'int' <LValueToRValue>
+// CHECK-NEXT: `-DeclRefExpr {{.*}} <col:12> 'int' lvalue ParmVar {{.*}} 'i' 'int'
+
+namespace TestInvalidFunctionDecl {
+struct Str {
+ double foo1(double, invalid_type);
+};
+double Str::foo1(double, invalid_type)
+{ return 45; }
+}
+// CHECK: NamespaceDecl {{.*}} <{{.*}}> {{.*}} TestInvalidFunctionDecl
+// CHECK-NEXT: |-CXXRecordDecl {{.*}} <line:46:1, line:48:1> line:46:8 struct Str definition
+// CHECK: | |-CXXRecordDecl {{.*}} <col:1, col:8> col:8 implicit struct Str
+// CHECK-NEXT: | `-CXXMethodDecl {{.*}} <line:47:4, col:36> col:11 invalid foo1 'double (double, int)'
+// CHECK-NEXT: | |-ParmVarDecl {{.*}} <col:16> col:22 'double'
+// CHECK-NEXT: | `-ParmVarDecl {{.*}} <col:24, <invalid sloc>> col:36 invalid 'int'
+// CHECK-NEXT: `-CXXMethodDecl {{.*}} parent {{.*}} <line:49:1, line:50:14> line:49:13 invalid foo1 'double (double, int)'
+// CHECK-NEXT: |-ParmVarDecl {{.*}} <col:18> col:24 'double'
+// CHECK-NEXT: |-ParmVarDecl {{.*}} <col:26, <invalid sloc>> col:38 invalid 'int'
+// CHECK-NEXT: `-CompoundStmt {{.*}} <line:50:1, col:14>
+// CHECK-NEXT: `-ReturnStmt {{.*}} <col:3, col:10>
+// CHECK-NEXT: `-ImplicitCastExpr {{.*}} <col:10> 'double' <IntegralToFloating>
+// CHECK-NEXT: `-IntegerLiteral {{.*}} <col:10> 'int' 45
-// RUN: %clang_cc1 -verify -fopenmp -ast-dump %s | FileCheck %s\r
-// expected-no-diagnostics\r
-\r
-int ga, gb;\r
-#pragma omp threadprivate(ga, gb)\r
-\r
-// CHECK: |-OMPThreadPrivateDecl {{.+}} <col:9> col:9\r
-// CHECK-NEXT: | |-DeclRefExpr {{.+}} <col:27> 'int' lvalue Var {{.+}} 'ga' 'int'\r
-// CHECK-NEXT: | `-DeclRefExpr {{.+}} <col:31> 'int' lvalue Var {{.+}} 'gb' 'int'\r
-\r
-#pragma omp declare reduction(+ : int, char : omp_out *= omp_in)\r
-\r
-#pragma omp declare reduction(fun : float : omp_out += omp_in) initializer(omp_priv = omp_orig + 15)\r
-\r
-// CHECK: |-OMPDeclareReductionDecl {{.+}} <line:11:35> col:35 operator+ 'int' combiner\r
-// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} <col:47, col:58> 'int' lvalue '*=' ComputeLHSTy='int' ComputeResultTy='int'\r
-// CHECK-NEXT: | | |-DeclRefExpr {{.+}} <col:47> 'int' lvalue Var {{.+}} 'omp_out' 'int'\r
-// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:58> 'int' <LValueToRValue>\r
-// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:58> 'int' lvalue Var {{.+}} 'omp_in' 'int'\r
-// CHECK-NEXT: | |-VarDecl {{.+}} <col:35> col:35 implicit used omp_in 'int'\r
-// CHECK-NEXT: | `-VarDecl {{.+}} <col:35> col:35 implicit used omp_out 'int'\r
-// CHECK-NEXT: |-OMPDeclareReductionDecl {{.+}} <col:40> col:40 operator+ 'char' combiner\r
-// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} <col:47, col:58> 'char' lvalue '*=' ComputeLHSTy='int' ComputeResultTy='int'\r
-// CHECK-NEXT: | | |-DeclRefExpr {{.+}} <col:47> 'char' lvalue Var {{.+}} 'omp_out' 'char'\r
-// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:58> 'int' <IntegralCast>\r
-// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:58> 'char' <LValueToRValue>\r
-// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:58> 'char' lvalue Var {{.+}} 'omp_in' 'char'\r
-// CHECK-NEXT: | |-VarDecl {{.+}} <col:40> col:40 implicit used omp_in 'char'\r
-// CHECK-NEXT: | `-VarDecl {{.+}} <col:40> col:40 implicit used omp_out 'char'\r
-// CHECK-NEXT: |-OMPDeclareReductionDecl {{.+}} <line:13:37> col:37 fun 'float' combiner initializer\r
-// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} <col:45, col:56> 'float' lvalue '+=' ComputeLHSTy='float' ComputeResultTy='float'\r
-// CHECK-NEXT: | | |-DeclRefExpr {{.+}} <col:45> 'float' lvalue Var {{.+}} 'omp_out' 'float'\r
-// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:56> 'float' <LValueToRValue>\r
-// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:56> 'float' lvalue Var {{.+}} 'omp_in' 'float'\r
-\r
-struct S {\r
- int a, b;\r
- S() {\r
-#pragma omp parallel for default(none) private(a) shared(b) schedule(static, a)\r
- for (int i = 0; i < 0; ++i)\r
- ++a;\r
- }\r
-};\r
-\r
-// CHECK: | `-OMPParallelForDirective {{.+}} <line:39:9, col:80>\r
-// CHECK-NEXT: | |-OMPDefaultClause {{.+}} <col:26, col:40>\r
-// CHECK-NEXT: | |-OMPPrivateClause {{.+}} <col:40, col:51>\r
-// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:48> 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &'\r
-// CHECK-NEXT: | |-OMPSharedClause {{.+}} <col:51, col:61>\r
-// CHECK-NEXT: | | `-MemberExpr {{.+}} <col:58> 'int' lvalue ->b\r
-// CHECK-NEXT: | | `-CXXThisExpr {{.+}} <col:58> 'S *' this\r
-// CHECK-NEXT: | |-OMPScheduleClause {{.+}} <col:61, col:79>\r
-// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:78> 'int' <LValueToRValue>\r
-// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:78> 'int' lvalue OMPCapturedExpr {{.+}} '.capture_expr.' 'int'\r
-// CHECK-NEXT: | |-CapturedStmt {{.+}} <line:40:5, line:41:9>\r
-// CHECK-NEXT: | | |-CapturedDecl {{.+}} <<invalid sloc>> <invalid sloc>\r
-// CHECK-NEXT: | | | |-ForStmt {{.+}} <line:40:5, line:41:9>\r
-// CHECK: | | | | `-UnaryOperator {{.+}} <line:41:7, col:9> 'int' lvalue prefix '++'\r
-// CHECK-NEXT: | | | | `-DeclRefExpr {{.+}} <col:9> 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &'\r
-\r
-#pragma omp declare simd\r
-#pragma omp declare simd inbranch\r
-void foo();\r
-\r
-// CHECK: `-FunctionDecl {{.+}} <line:63:1, col:10> col:6 foo 'void ()'\r
-// CHECK-NEXT: |-OMPDeclareSimdDeclAttr {{.+}} <line:62:9, col:34> Implicit BS_Inbranch\r
-// CHECK: `-OMPDeclareSimdDeclAttr {{.+}} <line:61:9, col:25> Implicit BS_Undefined\r
-\r
+// RUN: %clang_cc1 -verify -fopenmp -ast-dump %s | FileCheck %s
+// expected-no-diagnostics
+
+int ga, gb;
+#pragma omp threadprivate(ga, gb)
+
+// CHECK: |-OMPThreadPrivateDecl {{.+}} <col:9> col:9
+// CHECK-NEXT: | |-DeclRefExpr {{.+}} <col:27> 'int' lvalue Var {{.+}} 'ga' 'int'
+// CHECK-NEXT: | `-DeclRefExpr {{.+}} <col:31> 'int' lvalue Var {{.+}} 'gb' 'int'
+
+#pragma omp declare reduction(+ : int, char : omp_out *= omp_in)
+
+#pragma omp declare reduction(fun : float : omp_out += omp_in) initializer(omp_priv = omp_orig + 15)
+
+// CHECK: |-OMPDeclareReductionDecl {{.+}} <line:11:35> col:35 operator+ 'int' combiner
+// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} <col:47, col:58> 'int' lvalue '*=' ComputeLHSTy='int' ComputeResultTy='int'
+// CHECK-NEXT: | | |-DeclRefExpr {{.+}} <col:47> 'int' lvalue Var {{.+}} 'omp_out' 'int'
+// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:58> 'int' <LValueToRValue>
+// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:58> 'int' lvalue Var {{.+}} 'omp_in' 'int'
+// CHECK-NEXT: | |-VarDecl {{.+}} <col:35> col:35 implicit used omp_in 'int'
+// CHECK-NEXT: | `-VarDecl {{.+}} <col:35> col:35 implicit used omp_out 'int'
+// CHECK-NEXT: |-OMPDeclareReductionDecl {{.+}} <col:40> col:40 operator+ 'char' combiner
+// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} <col:47, col:58> 'char' lvalue '*=' ComputeLHSTy='int' ComputeResultTy='int'
+// CHECK-NEXT: | | |-DeclRefExpr {{.+}} <col:47> 'char' lvalue Var {{.+}} 'omp_out' 'char'
+// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:58> 'int' <IntegralCast>
+// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:58> 'char' <LValueToRValue>
+// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:58> 'char' lvalue Var {{.+}} 'omp_in' 'char'
+// CHECK-NEXT: | |-VarDecl {{.+}} <col:40> col:40 implicit used omp_in 'char'
+// CHECK-NEXT: | `-VarDecl {{.+}} <col:40> col:40 implicit used omp_out 'char'
+// CHECK-NEXT: |-OMPDeclareReductionDecl {{.+}} <line:13:37> col:37 fun 'float' combiner initializer
+// CHECK-NEXT: | |-CompoundAssignOperator {{.+}} <col:45, col:56> 'float' lvalue '+=' ComputeLHSTy='float' ComputeResultTy='float'
+// CHECK-NEXT: | | |-DeclRefExpr {{.+}} <col:45> 'float' lvalue Var {{.+}} 'omp_out' 'float'
+// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:56> 'float' <LValueToRValue>
+// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:56> 'float' lvalue Var {{.+}} 'omp_in' 'float'
+
+struct S {
+ int a, b;
+ S() {
+#pragma omp parallel for default(none) private(a) shared(b) schedule(static, a)
+ for (int i = 0; i < 0; ++i)
+ ++a;
+ }
+};
+
+// CHECK: | `-OMPParallelForDirective {{.+}} <line:39:9, col:80>
+// CHECK-NEXT: | |-OMPDefaultClause {{.+}} <col:26, col:40>
+// CHECK-NEXT: | |-OMPPrivateClause {{.+}} <col:40, col:51>
+// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:48> 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &'
+// CHECK-NEXT: | |-OMPSharedClause {{.+}} <col:51, col:61>
+// CHECK-NEXT: | | `-MemberExpr {{.+}} <col:58> 'int' lvalue ->b
+// CHECK-NEXT: | | `-CXXThisExpr {{.+}} <col:58> 'struct S *' this
+// CHECK-NEXT: | |-OMPScheduleClause {{.+}} <col:61, col:79>
+// CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <col:78> 'int' <LValueToRValue>
+// CHECK-NEXT: | | `-DeclRefExpr {{.+}} <col:78> 'int' lvalue OMPCapturedExpr {{.+}} '.capture_expr.' 'int'
+// CHECK-NEXT: | |-CapturedStmt {{.+}} <line:40:5, line:41:9>
+// CHECK-NEXT: | | |-CapturedDecl {{.+}} <<invalid sloc>> <invalid sloc>
+// CHECK-NEXT: | | | |-ForStmt {{.+}} <line:40:5, line:41:9>
+// CHECK: | | | | `-UnaryOperator {{.+}} <line:41:7, col:9> 'int' lvalue prefix '++'
+// CHECK-NEXT: | | | | `-DeclRefExpr {{.+}} <col:9> 'int' lvalue OMPCapturedExpr {{.+}} 'a' 'int &'
+
+#pragma omp declare simd
+#pragma omp declare simd inbranch
+void foo();
+
+// CHECK: `-FunctionDecl {{.+}} <line:63:1, col:10> col:6 foo 'void (void)'
+// CHECK-NEXT: |-OMPDeclareSimdDeclAttr {{.+}} <line:62:9, col:34> Implicit BS_Inbranch
+// CHECK: `-OMPDeclareSimdDeclAttr {{.+}} <line:61:9, col:25> Implicit BS_Undefined
+
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -std=c++11 -ast-dump %s | FileCheck %s\r
-// CHECK: CXXCtorInitializer Field {{.*}} 'ptr' 'void *'\r
-// CHECK: CXXCtorInitializer Field {{.*}} 'q' 'Q'\r
-\r
-@interface NSObject\r
-@end\r
-\r
-@interface I : NSObject\r
-@end\r
-\r
-struct Q { Q(); };\r
-\r
-struct S {\r
- S();\r
- void *ptr = nullptr;\r
- Q q;\r
-};\r
-\r
-@implementation I\r
-S::S() {}\r
-@end\r
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.10 -std=c++11 -ast-dump %s | FileCheck %s
+// CHECK: CXXCtorInitializer Field {{.*}} 'ptr' 'void *'
+// CHECK: CXXCtorInitializer Field {{.*}} 'q' 'struct Q'
+
+@interface NSObject
+@end
+
+@interface I : NSObject
+@end
+
+struct Q { Q(); };
+
+struct S {
+ S();
+ void *ptr = nullptr;
+ Q q;
+};
+
+@implementation I
+S::S() {}
+@end
-// RUN: %clang_cc1 -fsyntax-only -std=c++03 -verify -ast-dump %s > %t-03\r
-// RUN: FileCheck --input-file=%t-03 %s\r
-// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -ast-dump %s > %t-11\r
-// RUN: FileCheck --input-file=%t-11 %s\r
-// RUN: FileCheck --input-file=%t-11 %s --check-prefix=CHECK-CXX11\r
-\r
-// http://llvm.org/PR7905\r
-namespace PR7905 {\r
-struct S; // expected-note {{forward declaration}}\r
-void foo1() {\r
- (void)(S[]) {{3}}; // expected-error {{array has incomplete element type}}\r
-}\r
-\r
-template <typename T> struct M { T m; };\r
-void foo2() {\r
- (void)(M<short> []) {{3}};\r
-}\r
-}\r
-\r
-// Check compound literals mixed with C++11 list-initialization.\r
-namespace brace_initializers {\r
- struct POD {\r
- int x, y;\r
- };\r
- struct HasCtor {\r
- HasCtor(int x, int y);\r
- };\r
- struct HasDtor {\r
- int x, y;\r
- ~HasDtor();\r
- };\r
- struct HasCtorDtor {\r
- HasCtorDtor(int x, int y);\r
- ~HasCtorDtor();\r
- };\r
-\r
- void test() {\r
- (void)(POD){1, 2};\r
- // CHECK-NOT: CXXBindTemporaryExpr {{.*}} 'brace_initializers::POD'\r
- // CHECK: CompoundLiteralExpr {{.*}} 'brace_initializers::POD'\r
- // CHECK-NEXT: InitListExpr {{.*}} 'brace_initializers::POD'\r
- // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}\r
- // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}\r
-\r
- (void)(HasDtor){1, 2};\r
- // CHECK: CXXBindTemporaryExpr {{.*}} 'brace_initializers::HasDtor'\r
- // CHECK-NEXT: CompoundLiteralExpr {{.*}} 'brace_initializers::HasDtor'\r
- // CHECK-NEXT: InitListExpr {{.*}} 'brace_initializers::HasDtor'\r
- // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}\r
- // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}\r
-\r
-#if __cplusplus >= 201103L\r
- (void)(HasCtor){1, 2};\r
- // CHECK-CXX11-NOT: CXXBindTemporaryExpr {{.*}} 'brace_initializers::HasCtor'\r
- // CHECK-CXX11: CompoundLiteralExpr {{.*}} 'brace_initializers::HasCtor'\r
- // CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'brace_initializers::HasCtor'\r
- // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}\r
- // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}}\r
-\r
- (void)(HasCtorDtor){1, 2};\r
- // CHECK-CXX11: CXXBindTemporaryExpr {{.*}} 'brace_initializers::HasCtorDtor'\r
- // CHECK-CXX11-NEXT: CompoundLiteralExpr {{.*}} 'brace_initializers::HasCtorDtor'\r
- // CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'brace_initializers::HasCtorDtor'\r
- // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}\r
- // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}}\r
-#endif\r
- }\r
-\r
- struct PrivateDtor {\r
- int x, y;\r
- private:\r
- ~PrivateDtor(); // expected-note {{declared private here}}\r
- };\r
-\r
- void testPrivateDtor() {\r
- (void)(PrivateDtor){1, 2}; // expected-error {{temporary of type 'brace_initializers::PrivateDtor' has private destructor}}\r
- }\r
-}\r
-\r
-// This doesn't necessarily need to be an error, but CodeGen can't handle it\r
-// at the moment.\r
-int PR17415 = (int){PR17415}; // expected-error {{initializer element is not a compile-time constant}}\r
-\r
-// Make sure we accept this. (Not sure if we actually should... but we do\r
-// at the moment.)\r
-template<unsigned> struct Value { };\r
-template<typename T>\r
-int &check_narrowed(Value<sizeof((T){1.1})>);\r
-\r
-#if __cplusplus >= 201103L\r
-// Compound literals in global lambdas have automatic storage duration\r
-// and are not subject to the constant-initialization rules.\r
-int computed_with_lambda = [] {\r
- int x = 5;\r
- int result = ((int[]) { x, x + 2, x + 4, x + 6 })[0];\r
- return result;\r
-}();\r
-#endif\r
+// RUN: %clang_cc1 -fsyntax-only -std=c++03 -verify -ast-dump %s > %t-03
+// RUN: FileCheck --input-file=%t-03 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -ast-dump %s > %t-11
+// RUN: FileCheck --input-file=%t-11 %s
+// RUN: FileCheck --input-file=%t-11 %s --check-prefix=CHECK-CXX11
+
+// http://llvm.org/PR7905
+namespace PR7905 {
+struct S; // expected-note {{forward declaration}}
+void foo1() {
+ (void)(S[]) {{3}}; // expected-error {{array has incomplete element type}}
+}
+
+template <typename T> struct M { T m; };
+void foo2() {
+ (void)(M<short> []) {{3}};
+}
+}
+
+// Check compound literals mixed with C++11 list-initialization.
+namespace brace_initializers {
+ struct POD {
+ int x, y;
+ };
+ struct HasCtor {
+ HasCtor(int x, int y);
+ };
+ struct HasDtor {
+ int x, y;
+ ~HasDtor();
+ };
+ struct HasCtorDtor {
+ HasCtorDtor(int x, int y);
+ ~HasCtorDtor();
+ };
+
+ void test() {
+ (void)(POD){1, 2};
+ // CHECK-NOT: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::POD'
+ // CHECK: CompoundLiteralExpr {{.*}} 'struct brace_initializers::POD'
+ // CHECK-NEXT: InitListExpr {{.*}} 'struct brace_initializers::POD'
+ // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
+ // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}
+
+ (void)(HasDtor){1, 2};
+ // CHECK: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::HasDtor'
+ // CHECK-NEXT: CompoundLiteralExpr {{.*}} 'struct brace_initializers::HasDtor'
+ // CHECK-NEXT: InitListExpr {{.*}} 'struct brace_initializers::HasDtor'
+ // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
+ // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}
+
+#if __cplusplus >= 201103L
+ (void)(HasCtor){1, 2};
+ // CHECK-CXX11-NOT: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::HasCtor'
+ // CHECK-CXX11: CompoundLiteralExpr {{.*}} 'struct brace_initializers::HasCtor'
+ // CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'struct brace_initializers::HasCtor'
+ // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}
+ // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}}
+
+ (void)(HasCtorDtor){1, 2};
+ // CHECK-CXX11: CXXBindTemporaryExpr {{.*}} 'struct brace_initializers::HasCtorDtor'
+ // CHECK-CXX11-NEXT: CompoundLiteralExpr {{.*}} 'struct brace_initializers::HasCtorDtor'
+ // CHECK-CXX11-NEXT: CXXTemporaryObjectExpr {{.*}} 'struct brace_initializers::HasCtorDtor'
+ // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 1{{$}}
+ // CHECK-CXX11-NEXT: IntegerLiteral {{.*}} 2{{$}}
+#endif
+ }
+
+ struct PrivateDtor {
+ int x, y;
+ private:
+ ~PrivateDtor(); // expected-note {{declared private here}}
+ };
+
+ void testPrivateDtor() {
+ (void)(PrivateDtor){1, 2}; // expected-error {{temporary of type 'brace_initializers::PrivateDtor' has private destructor}}
+ }
+}
+
+// This doesn't necessarily need to be an error, but CodeGen can't handle it
+// at the moment.
+int PR17415 = (int){PR17415}; // expected-error {{initializer element is not a compile-time constant}}
+
+// Make sure we accept this. (Not sure if we actually should... but we do
+// at the moment.)
+template<unsigned> struct Value { };
+template<typename T>
+int &check_narrowed(Value<sizeof((T){1.1})>);
+
+#if __cplusplus >= 201103L
+// Compound literals in global lambdas have automatic storage duration
+// and are not subject to the constant-initialization rules.
+int computed_with_lambda = [] {
+ int x = 5;
+ int result = ((int[]) { x, x + 2, x + 4, x + 6 })[0];
+ return result;
+}();
+#endif
-// RUN: %clang_cc1 -triple i686-mingw32 -ast-dump %s | FileCheck %s\r
-\r
-template<class T>\r
-class P {\r
- public:\r
- P(T* t) {}\r
-};\r
-\r
-namespace foo {\r
-class A { public: A(int = 0) {} };\r
-enum B {};\r
-typedef int C;\r
-}\r
-\r
-// CHECK: VarDecl {{0x[0-9a-fA-F]+}} <line:16:1, col:36> col:15 ImplicitConstrArray 'foo::A [2]'\r
-static foo::A ImplicitConstrArray[2];\r
-\r
-int main() {\r
- // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::A *'\r
- P<foo::A> p14 = new foo::A;\r
- // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::B *'\r
- P<foo::B> p24 = new foo::B;\r
- // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::C *'\r
- P<foo::C> pr4 = new foo::C;\r
-}\r
-\r
-foo::A getName() {\r
- // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:10, col:17> 'foo::A'\r
- return foo::A();\r
-}\r
-\r
-void destruct(foo::A *a1, foo::A *a2, P<int> *p1) {\r
- // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:8> '<bound member function type>' ->~A\r
- a1->~A();\r
- // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:16> '<bound member function type>' ->~A\r
- a2->foo::A::~A();\r
- // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:13> '<bound member function type>' ->~P\r
- p1->~P<int>();\r
-}\r
-\r
-struct D {\r
- D(int);\r
- ~D();\r
-};\r
-\r
-void construct() {\r
- using namespace foo;\r
- A a = A(12);\r
- // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:9, col:13> 'foo::A' 'void (int){{( __attribute__\(\(thiscall\)\))?}}'\r
- D d = D(12);\r
- // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:9, col:13> 'D' 'void (int){{( __attribute__\(\(thiscall\)\))?}}'\r
-}\r
+// RUN: %clang_cc1 -triple i686-mingw32 -ast-dump %s | FileCheck %s
+
+template<class T>
+class P {
+ public:
+ P(T* t) {}
+};
+
+namespace foo {
+class A { public: A(int = 0) {} };
+enum B {};
+typedef int C;
+}
+
+// CHECK: VarDecl {{0x[0-9a-fA-F]+}} <line:16:1, col:36> col:15 ImplicitConstrArray 'foo::A [2]'
+static foo::A ImplicitConstrArray[2];
+
+int main() {
+ // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::A *'
+ P<foo::A> p14 = new foo::A;
+ // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::B *'
+ P<foo::B> p24 = new foo::B;
+ // CHECK: CXXNewExpr {{0x[0-9a-fA-F]+}} <col:19, col:28> 'foo::C *'
+ P<foo::C> pr4 = new foo::C;
+}
+
+foo::A getName() {
+ // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:10, col:17> 'foo::A'
+ return foo::A();
+}
+
+void destruct(foo::A *a1, foo::A *a2, P<int> *p1) {
+ // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:8> '<bound member function type>' ->~A
+ a1->~A();
+ // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:16> '<bound member function type>' ->~A
+ a2->foo::A::~A();
+ // CHECK: MemberExpr {{0x[0-9a-fA-F]+}} <col:3, col:13> '<bound member function type>' ->~P
+ p1->~P<int>();
+}
+
+struct D {
+ D(int);
+ ~D();
+};
+
+void construct() {
+ using namespace foo;
+ A a = A(12);
+ // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:9, col:13> 'class foo::A' 'void (int){{( __attribute__\(\(thiscall\)\))?}}'
+ D d = D(12);
+ // CHECK: CXXConstructExpr {{0x[0-9a-fA-F]+}} <col:9, col:13> 'struct D' 'void (int){{( __attribute__\(\(thiscall\)\))?}}'
+}
-// RUN: %clang_cc1 -fsyntax-only -Wredundant-move -std=c++11 -verify %s\r
-// RUN: %clang_cc1 -fsyntax-only -Wredundant-move -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s\r
-// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -ast-dump | FileCheck %s --check-prefix=CHECK-AST\r
-\r
-// definitions for std::move\r
-namespace std {\r
-inline namespace foo {\r
-template <class T> struct remove_reference { typedef T type; };\r
-template <class T> struct remove_reference<T&> { typedef T type; };\r
-template <class T> struct remove_reference<T&&> { typedef T type; };\r
-\r
-template <class T> typename remove_reference<T>::type &&move(T &&t);\r
-}\r
-}\r
-\r
-// test1 and test2 should not warn until after implementation of DR1579.\r
-struct A {};\r
-struct B : public A {};\r
-\r
-A test1(B b1) {\r
- B b2;\r
- return b1;\r
- return b2;\r
- return std::move(b1);\r
- return std::move(b2);\r
-}\r
-\r
-struct C {\r
- C() {}\r
- C(A) {}\r
-};\r
-\r
-C test2(A a1, B b1) {\r
- A a2;\r
- B b2;\r
-\r
- return a1;\r
- return a2;\r
- return b1;\r
- return b2;\r
-\r
- return std::move(a1);\r
- return std::move(a2);\r
- return std::move(b1);\r
- return std::move(b2);\r
-}\r
-\r
-// Copy of tests above with types changed to reference types.\r
-A test3(B& b1) {\r
- B& b2 = b1;\r
- return b1;\r
- return b2;\r
- return std::move(b1);\r
- return std::move(b2);\r
-}\r
-\r
-C test4(A& a1, B& b1) {\r
- A& a2 = a1;\r
- B& b2 = b1;\r
-\r
- return a1;\r
- return a2;\r
- return b1;\r
- return b2;\r
-\r
- return std::move(a1);\r
- return std::move(a2);\r
- return std::move(b1);\r
- return std::move(b2);\r
-}\r
-\r
-// PR23819, case 2\r
-struct D {};\r
-D test5(D d) {\r
- return d;\r
- // Verify the implicit move from the AST dump\r
- // CHECK-AST: ReturnStmt{{.*}}line:[[@LINE-2]]\r
- // CHECK-AST-NEXT: CXXConstructExpr{{.*}}D{{.*}}void (D &&)\r
- // CHECK-AST-NEXT: ImplicitCastExpr\r
- // CHECK-AST-NEXT: DeclRefExpr{{.*}}ParmVar{{.*}}'d'\r
-\r
- return std::move(d);\r
- // expected-warning@-1{{redundant move in return statement}}\r
- // expected-note@-2{{remove std::move call here}}\r
- // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""\r
- // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:21-[[@LINE-4]]:22}:""\r
-}\r
-\r
-namespace templates {\r
- struct A {};\r
- struct B { B(A); };\r
-\r
- // Warn once here since the type is not dependent.\r
- template <typename T>\r
- A test1(A a) {\r
- return std::move(a);\r
- // expected-warning@-1{{redundant move in return statement}}\r
- // expected-note@-2{{remove std::move call here}}\r
- // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:22}:""\r
- // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""\r
- }\r
- void run_test1() {\r
- test1<A>(A());\r
- test1<B>(A());\r
- }\r
-\r
- // T1 and T2 may not be the same, the warning may not always apply.\r
- template <typename T1, typename T2>\r
- T1 test2(T2 t) {\r
- return std::move(t);\r
- }\r
- void run_test2() {\r
- test2<A, A>(A());\r
- test2<B, A>(A());\r
- }\r
-}\r
+// RUN: %clang_cc1 -fsyntax-only -Wredundant-move -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wredundant-move -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -ast-dump | FileCheck %s --check-prefix=CHECK-AST
+
+// definitions for std::move
+namespace std {
+inline namespace foo {
+template <class T> struct remove_reference { typedef T type; };
+template <class T> struct remove_reference<T&> { typedef T type; };
+template <class T> struct remove_reference<T&&> { typedef T type; };
+
+template <class T> typename remove_reference<T>::type &&move(T &&t);
+}
+}
+
+// test1 and test2 should not warn until after implementation of DR1579.
+struct A {};
+struct B : public A {};
+
+A test1(B b1) {
+ B b2;
+ return b1;
+ return b2;
+ return std::move(b1);
+ return std::move(b2);
+}
+
+struct C {
+ C() {}
+ C(A) {}
+};
+
+C test2(A a1, B b1) {
+ A a2;
+ B b2;
+
+ return a1;
+ return a2;
+ return b1;
+ return b2;
+
+ return std::move(a1);
+ return std::move(a2);
+ return std::move(b1);
+ return std::move(b2);
+}
+
+// Copy of tests above with types changed to reference types.
+A test3(B& b1) {
+ B& b2 = b1;
+ return b1;
+ return b2;
+ return std::move(b1);
+ return std::move(b2);
+}
+
+C test4(A& a1, B& b1) {
+ A& a2 = a1;
+ B& b2 = b1;
+
+ return a1;
+ return a2;
+ return b1;
+ return b2;
+
+ return std::move(a1);
+ return std::move(a2);
+ return std::move(b1);
+ return std::move(b2);
+}
+
+// PR23819, case 2
+struct D {};
+D test5(D d) {
+ return d;
+ // Verify the implicit move from the AST dump
+ // CHECK-AST: ReturnStmt{{.*}}line:[[@LINE-2]]
+ // CHECK-AST-NEXT: CXXConstructExpr{{.*}}struct D{{.*}}void (struct D &&)
+ // CHECK-AST-NEXT: ImplicitCastExpr
+ // CHECK-AST-NEXT: DeclRefExpr{{.*}}ParmVar{{.*}}'d'
+
+ return std::move(d);
+ // expected-warning@-1{{redundant move in return statement}}
+ // expected-note@-2{{remove std::move call here}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:21-[[@LINE-4]]:22}:""
+}
+
+namespace templates {
+ struct A {};
+ struct B { B(A); };
+
+ // Warn once here since the type is not dependent.
+ template <typename T>
+ A test1(A a) {
+ return std::move(a);
+ // expected-warning@-1{{redundant move in return statement}}
+ // expected-note@-2{{remove std::move call here}}
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:22}:""
+ // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
+ }
+ void run_test1() {
+ test1<A>(A());
+ test1<B>(A());
+ }
+
+ // T1 and T2 may not be the same, the warning may not always apply.
+ template <typename T1, typename T2>
+ T1 test2(T2 t) {
+ return std::move(t);
+ }
+ void run_test2() {
+ test2<A, A>(A());
+ test2<B, A>(A());
+ }
+}
-// RUN: %clang_cc1 -triple x86_64-apple-macosx10.11.0 -std=gnu++11 -o /dev/null -x objective-c++ -fblocks -ast-dump %s 2>&1 | FileCheck %s\r
-\r
-// CHECK: -FunctionDecl {{.*}} test 'id ()'\r
-// CHECK-NEXT: -CompoundStmt\r
-// CHECK-NEXT: -ReturnStmt\r
-// CHECK-NEXT: -ExprWithCleanups\r
-// CHECK-NEXT: -cleanup Block\r
-// CHECK-NEXT: -cleanup Block\r
-\r
-@interface NSDictionary\r
-+ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;\r
-@end\r
-\r
-id test() {\r
- return @{@"a": [](){}, @"b": [](){}};\r
-}\r
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.11.0 -std=gnu++11 -o /dev/null -x objective-c++ -fblocks -ast-dump %s 2>&1 | FileCheck %s
+
+// CHECK: -FunctionDecl {{.*}} test 'id (void)'
+// CHECK-NEXT: -CompoundStmt
+// CHECK-NEXT: -ReturnStmt
+// CHECK-NEXT: -ExprWithCleanups
+// CHECK-NEXT: -cleanup Block
+// CHECK-NEXT: -cleanup Block
+
+@interface NSDictionary
++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
+@end
+
+id test() {
+ return @{@"a": [](){}, @"b": [](){}};
+}
public: enum { kSomeConst = 128 };
bar(int x = kSomeConst) {}
};
-
- // CHECK: FunctionDecl{{.*}}f 'void ()'
+
+ // CHECK: FunctionDecl{{.*}}f 'void (void)'
void f() {
// CHECK: VarDecl{{.*}}tmp 'bar<int>'
// CHECK: CXXDefaultArgExpr{{.*}}'int'
-// RUN: %clang_cc1 -std=c++14 -verify -ast-dump %s | FileCheck %s\r
-// expected-no-diagnostics\r
-\r
-// CHECK: FunctionDecl {{.*}} used func 'void ()'\r
-// CHECK-NEXT: TemplateArgument type 'int'\r
-// CHECK: LambdaExpr {{.*}} '(lambda at\r
-// CHECK: ParmVarDecl {{.*}} used f 'foo' cinit\r
-// CHECK-NEXT: DeclRefExpr {{.*}} 'foo' EnumConstant {{.*}} 'a' 'foo'\r
-\r
-namespace PR28795 {\r
- template<typename T>\r
- void func() {\r
- enum class foo { a, b };\r
- auto bar = [](foo f = foo::a) { return f; };\r
- bar();\r
- }\r
-\r
- void foo() {\r
- func<int>();\r
- }\r
-}\r
-\r
-// CHECK: ClassTemplateSpecializationDecl {{.*}} struct class2 definition\r
-// CHECK: TemplateArgument type 'int'\r
-// CHECK: LambdaExpr {{.*}} '(lambda at\r
-// CHECK: ParmVarDecl {{.*}} used f 'foo' cinit\r
-// CHECK-NEXT: DeclRefExpr {{.*}} 'foo' EnumConstant {{.*}} 'a' 'foo'\r
-\r
-// Template struct case:\r
-template <class T> struct class2 {\r
- void bar() {\r
- enum class foo { a, b };\r
- [](foo f = foo::a) { return f; }();\r
- }\r
-};\r
-\r
-template struct class2<int>;\r
-\r
-// CHECK: FunctionTemplateDecl {{.*}} f1\r
-// CHECK-NEXT: TemplateTypeParmDecl {{.*}} typename depth 0 index 0 T\r
-// CHECK-NEXT: FunctionDecl {{.*}} f1 'void ()'\r
-// CHECK: FunctionDecl {{.*}} f1 'void ()'\r
-// CHECK-NEXT: TemplateArgument type 'int'\r
-// CHECK: ParmVarDecl {{.*}} n 'foo' cinit\r
-// CHECK-NEXT: DeclRefExpr {{.*}} 'foo' EnumConstant {{.*}} 'a' 'foo'\r
-\r
-template<typename T>\r
-void f1() {\r
- enum class foo { a, b };\r
- struct S {\r
- int g1(foo n = foo::a);\r
- };\r
-}\r
-\r
-template void f1<int>();\r
+// RUN: %clang_cc1 -std=c++14 -verify -ast-dump %s | FileCheck %s
+// expected-no-diagnostics
+
+// CHECK: FunctionDecl {{.*}} used func 'void (void)'
+// CHECK-NEXT: TemplateArgument type 'int'
+// CHECK: LambdaExpr {{.*}} 'class (lambda at
+// CHECK: ParmVarDecl {{.*}} used f 'enum foo' cinit
+// CHECK-NEXT: DeclRefExpr {{.*}} 'enum foo' EnumConstant {{.*}} 'a' 'enum foo'
+
+namespace PR28795 {
+ template<typename T>
+ void func() {
+ enum class foo { a, b };
+ auto bar = [](foo f = foo::a) { return f; };
+ bar();
+ }
+
+ void foo() {
+ func<int>();
+ }
+}
+
+// CHECK: ClassTemplateSpecializationDecl {{.*}} struct class2 definition
+// CHECK: TemplateArgument type 'int'
+// CHECK: LambdaExpr {{.*}} 'class (lambda at
+// CHECK: ParmVarDecl {{.*}} used f 'enum foo' cinit
+// CHECK-NEXT: DeclRefExpr {{.*}} 'enum foo' EnumConstant {{.*}} 'a' 'enum foo'
+
+// Template struct case:
+template <class T> struct class2 {
+ void bar() {
+ enum class foo { a, b };
+ [](foo f = foo::a) { return f; }();
+ }
+};
+
+template struct class2<int>;
+
+// CHECK: FunctionTemplateDecl {{.*}} f1
+// CHECK-NEXT: TemplateTypeParmDecl {{.*}} typename depth 0 index 0 T
+// CHECK-NEXT: FunctionDecl {{.*}} f1 'void (void)'
+// CHECK: FunctionDecl {{.*}} f1 'void (void)'
+// CHECK-NEXT: TemplateArgument type 'int'
+// CHECK: ParmVarDecl {{.*}} n 'enum foo' cinit
+// CHECK-NEXT: DeclRefExpr {{.*}} 'enum foo' EnumConstant {{.*}} 'a' 'enum foo'
+
+template<typename T>
+void f1() {
+ enum class foo { a, b };
+ struct S {
+ int g1(foo n = foo::a);
+ };
+}
+
+template void f1<int>();