diff --git a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp index a28ef1138e539c..4e3f76544dc8b9 100644 --- a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp @@ -108,8 +108,7 @@ void AssertSideEffectCheck::check(const MatchFinder::MatchResult &Result) { StringRef MacroName = Lexer::getImmediateMacroName(Loc, SM, LangOpts); // Check if this macro is an assert. - if (std::find(AssertMacros.begin(), AssertMacros.end(), MacroName) != - AssertMacros.end()) { + if (llvm::is_contained(AssertMacros, MacroName)) { AssertMacroName = MacroName; break; } diff --git a/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp index a89831188b7e2f..eb54aaa994457e 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp @@ -132,9 +132,12 @@ void BranchCloneCheck::check(const MatchFinder::MatchResult &Result) { // We report the first occurence only when we find the second one. diag(Branches[i]->getBeginLoc(), "repeated branch in conditional chain"); - diag(Lexer::getLocForEndOfToken(Branches[i]->getEndLoc(), 0, - *Result.SourceManager, getLangOpts()), - "end of the original", DiagnosticIDs::Note); + SourceLocation End = + Lexer::getLocForEndOfToken(Branches[i]->getEndLoc(), 0, + *Result.SourceManager, getLangOpts()); + if (End.isValid()) { + diag(End, "end of the original", DiagnosticIDs::Note); + } } diag(Branches[j]->getBeginLoc(), "clone %0 starts here", @@ -208,10 +211,12 @@ void BranchCloneCheck::check(const MatchFinder::MatchResult &Result) { if (EndLoc.isMacroID()) EndLoc = Context.getSourceManager().getExpansionLoc(EndLoc); + EndLoc = Lexer::getLocForEndOfToken(EndLoc, 0, *Result.SourceManager, + getLangOpts()); - diag(Lexer::getLocForEndOfToken(EndLoc, 0, *Result.SourceManager, - getLangOpts()), - "last of these clones ends here", DiagnosticIDs::Note); + if (EndLoc.isValid()) { + diag(EndLoc, "last of these clones ends here", DiagnosticIDs::Note); + } } BeginCurrent = EndCurrent; } diff --git a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp index 57055ff2191e8c..2773d38420be35 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp @@ -105,7 +105,7 @@ void ForwardingReferenceOverloadCheck::check( // template as the function parameter of that type. (This implies that type // deduction will happen on the type.) const TemplateParameterList *Params = FuncTemplate->getTemplateParameters(); - if (std::find(Params->begin(), Params->end(), TypeParmDecl) == Params->end()) + if (!llvm::is_contained(*Params, TypeParmDecl)) return; // Every parameter after the first must have a default value. diff --git a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp index a5f9d6ed46054d..404b4beddd247b 100644 --- a/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp +++ b/clang-tools-extra/clang-tidy/fuchsia/MultipleInheritanceCheck.cpp @@ -93,7 +93,8 @@ void MultipleInheritanceCheck::registerMatchers(MatchFinder *Finder) { return; // Match declarations which have bases. - Finder->addMatcher(cxxRecordDecl(hasBases()).bind("decl"), this); + Finder->addMatcher( + cxxRecordDecl(allOf(hasBases(), isDefinition())).bind("decl"), this); } void MultipleInheritanceCheck::check(const MatchFinder::MatchResult &Result) { diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp index 45e59c3ec51abe..d0a95d95ec4b42 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp @@ -242,10 +242,8 @@ class CastSequenceVisitor : public RecursiveASTVisitor { getOutermostMacroName(StartLoc, SM, Context.getLangOpts()); // Check to see if the user wants to replace the macro being expanded. - if (std::find(NullMacros.begin(), NullMacros.end(), OutermostMacroName) == - NullMacros.end()) { + if (!llvm::is_contained(NullMacros, OutermostMacroName)) return skipSubTree(); - } StartLoc = SM.getFileLoc(StartLoc); EndLoc = SM.getFileLoc(EndLoc); @@ -327,8 +325,7 @@ class CastSequenceVisitor : public RecursiveASTVisitor { StringRef Name = Lexer::getImmediateMacroName(OldArgLoc, SM, Context.getLangOpts()); - return std::find(NullMacros.begin(), NullMacros.end(), Name) != - NullMacros.end(); + return llvm::is_contained(NullMacros, Name); } MacroLoc = SM.getExpansionRange(ArgLoc).getBegin(); diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index b48e307e6153f0..2d226b10334afc 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -5,6 +5,7 @@ add_clang_library(clangTidyReadabilityModule BracesAroundStatementsCheck.cpp ConstReturnTypeCheck.cpp ContainerSizeEmptyCheck.cpp + ConvertMemberFunctionsToStatic.cpp DeleteNullPointerCheck.cpp DeletedDefaultCheck.cpp ElseAfterReturnCheck.cpp diff --git a/clang-tools-extra/clang-tidy/readability/ConvertMemberFunctionsToStatic.cpp b/clang-tools-extra/clang-tidy/readability/ConvertMemberFunctionsToStatic.cpp new file mode 100644 index 00000000000000..f0e5b29dcab601 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/ConvertMemberFunctionsToStatic.cpp @@ -0,0 +1,172 @@ +//===--- ConvertMemberFunctionsToStatic.cpp - clang-tidy ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ConvertMemberFunctionsToStatic.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Basic/SourceLocation.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace readability { + +AST_MATCHER(CXXMethodDecl, isStatic) { return Node.isStatic(); } + +AST_MATCHER(CXXMethodDecl, hasTrivialBody) { return Node.hasTrivialBody(); } + +AST_MATCHER(CXXMethodDecl, isOverloadedOperator) { + return Node.isOverloadedOperator(); +} + +AST_MATCHER(CXXRecordDecl, hasAnyDependentBases) { + return Node.hasAnyDependentBases(); +} + +AST_MATCHER(CXXMethodDecl, isTemplate) { + return Node.getTemplatedKind() != FunctionDecl::TK_NonTemplate; +} + +AST_MATCHER(CXXMethodDecl, isDependentContext) { + return Node.isDependentContext(); +} + +AST_MATCHER(CXXMethodDecl, isInsideMacroDefinition) { + const ASTContext &Ctxt = Finder->getASTContext(); + return clang::Lexer::makeFileCharRange( + clang::CharSourceRange::getCharRange( + Node.getTypeSourceInfo()->getTypeLoc().getSourceRange()), + Ctxt.getSourceManager(), Ctxt.getLangOpts()) + .isInvalid(); +} + +AST_MATCHER_P(CXXMethodDecl, hasCanonicalDecl, + ast_matchers::internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(*Node.getCanonicalDecl(), Finder, Builder); +} + +AST_MATCHER(CXXMethodDecl, usesThis) { + class FindUsageOfThis : public RecursiveASTVisitor { + public: + bool Used = false; + + bool VisitCXXThisExpr(const CXXThisExpr *E) { + Used = true; + return false; // Stop traversal. + } + } UsageOfThis; + + // TraverseStmt does not modify its argument. + UsageOfThis.TraverseStmt(const_cast(Node.getBody())); + + return UsageOfThis.Used; +} + +void ConvertMemberFunctionsToStatic::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + cxxMethodDecl( + isDefinition(), isUserProvided(), + unless(anyOf( + isExpansionInSystemHeader(), isVirtual(), isStatic(), + hasTrivialBody(), isOverloadedOperator(), cxxConstructorDecl(), + cxxDestructorDecl(), cxxConversionDecl(), isTemplate(), + isDependentContext(), + ofClass(anyOf( + isLambda(), + hasAnyDependentBases()) // Method might become virtual + // depending on template base class. + ), + isInsideMacroDefinition(), + hasCanonicalDecl(isInsideMacroDefinition()), usesThis()))) + .bind("x"), + this); +} + +/// \brief Obtain the original source code text from a SourceRange. +static StringRef getStringFromRange(SourceManager &SourceMgr, + const LangOptions &LangOpts, + SourceRange Range) { + if (SourceMgr.getFileID(Range.getBegin()) != + SourceMgr.getFileID(Range.getEnd())) + return {}; + + return Lexer::getSourceText(CharSourceRange(Range, true), SourceMgr, + LangOpts); +} + +static SourceRange getLocationOfConst(const TypeSourceInfo *TSI, + SourceManager &SourceMgr, + const LangOptions &LangOpts) { + assert(TSI); + const auto FTL = TSI->getTypeLoc().IgnoreParens().getAs(); + assert(FTL); + + SourceRange Range{FTL.getRParenLoc().getLocWithOffset(1), + FTL.getLocalRangeEnd()}; + // Inside Range, there might be other keywords and trailing return types. + // Find the exact position of "const". + StringRef Text = getStringFromRange(SourceMgr, LangOpts, Range); + size_t Offset = Text.find("const"); + if (Offset == StringRef::npos) + return {}; + + SourceLocation Start = Range.getBegin().getLocWithOffset(Offset); + return {Start, Start.getLocWithOffset(strlen("const") - 1)}; +} + +void ConvertMemberFunctionsToStatic::check( + const MatchFinder::MatchResult &Result) { + const auto *Definition = Result.Nodes.getNodeAs("x"); + + // TODO: For out-of-line declarations, don't modify the source if the header + // is excluded by the -header-filter option. + DiagnosticBuilder Diag = + diag(Definition->getLocation(), "method %0 can be made static") + << Definition; + + // TODO: Would need to remove those in a fix-it. + if (Definition->getMethodQualifiers().hasVolatile() || + Definition->getMethodQualifiers().hasRestrict() || + Definition->getRefQualifier() != RQ_None) + return; + + const CXXMethodDecl *Declaration = Definition->getCanonicalDecl(); + + if (Definition->isConst()) { + // Make sure that we either remove 'const' on both declaration and + // definition or emit no fix-it at all. + SourceRange DefConst = getLocationOfConst(Definition->getTypeSourceInfo(), + *Result.SourceManager, + Result.Context->getLangOpts()); + + if (DefConst.isInvalid()) + return; + + if (Declaration != Definition) { + SourceRange DeclConst = getLocationOfConst( + Declaration->getTypeSourceInfo(), *Result.SourceManager, + Result.Context->getLangOpts()); + + if (DeclConst.isInvalid()) + return; + Diag << FixItHint::CreateRemoval(DeclConst); + } + + // Remove existing 'const' from both declaration and definition. + Diag << FixItHint::CreateRemoval(DefConst); + } + Diag << FixItHint::CreateInsertion(Declaration->getBeginLoc(), "static "); +} + +} // namespace readability +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/readability/ConvertMemberFunctionsToStatic.h b/clang-tools-extra/clang-tidy/readability/ConvertMemberFunctionsToStatic.h new file mode 100644 index 00000000000000..d9947650ab539a --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/ConvertMemberFunctionsToStatic.h @@ -0,0 +1,37 @@ +//===--- ConvertMemberFunctionsToStatic.h - clang-tidy ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_CONVERTMEMFUNCTOSTATIC_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_CONVERTMEMFUNCTOSTATIC_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// This check finds C++ class methods than can be made static +/// because they don't use the 'this' pointer. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/ +/// readability-convert-member-functions-to-static.html +class ConvertMemberFunctionsToStatic : public ClangTidyCheck { +public: + ConvertMemberFunctionsToStatic(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace readability +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_CONVERTMEMFUNCTOSTATIC_H diff --git a/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp b/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp index 6428f8cdc98932..eb3d7c505b831e 100644 --- a/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/NamespaceCommentCheck.cpp @@ -9,6 +9,7 @@ #include "NamespaceCommentCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Lex/Lexer.h" #include "llvm/ADT/StringExtras.h" @@ -181,7 +182,13 @@ void NamespaceCommentCheck::check(const MatchFinder::MatchResult &Result) { ? "anonymous namespace" : ("namespace '" + NestedNamespaceName.str() + "'"); - diag(AfterRBrace, Message) + // Place diagnostic at an old comment, or closing brace if we did not have it. + SourceLocation DiagLoc = + OldCommentRange.getBegin() != OldCommentRange.getEnd() + ? OldCommentRange.getBegin() + : ND->getRBraceLoc(); + + diag(DiagLoc, Message) << NamespaceName << FixItHint::CreateReplacement( CharSourceRange::getCharRange(OldCommentRange), diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index 5b2aed421bf119..5005ba3df61fd2 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -13,6 +13,7 @@ #include "BracesAroundStatementsCheck.h" #include "ConstReturnTypeCheck.h" #include "ContainerSizeEmptyCheck.h" +#include "ConvertMemberFunctionsToStatic.h" #include "DeleteNullPointerCheck.h" #include "DeletedDefaultCheck.h" #include "ElseAfterReturnCheck.h" @@ -57,6 +58,8 @@ class ReadabilityModule : public ClangTidyModule { "readability-const-return-type"); CheckFactories.registerCheck( "readability-container-size-empty"); + CheckFactories.registerCheck( + "readability-convert-member-functions-to-static"); CheckFactories.registerCheck( "readability-delete-null-pointer"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index 2b25058c9672ce..5f8b307f721a60 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -926,6 +926,13 @@ void ClangdLSPServer::onTypeHierarchy( Params.resolve, Params.direction, std::move(Reply)); } +void ClangdLSPServer::onResolveTypeHierarchy( + const ResolveTypeHierarchyItemParams &Params, + Callback> Reply) { + Server->resolveTypeHierarchy(Params.item, Params.resolve, Params.direction, + std::move(Reply)); +} + void ClangdLSPServer::applyConfiguration( const ConfigurationSettings &Settings) { // Per-file update to the compilation database. @@ -1021,6 +1028,7 @@ ClangdLSPServer::ClangdLSPServer( MsgHandler->bind("workspace/didChangeConfiguration", &ClangdLSPServer::onChangeConfiguration); MsgHandler->bind("textDocument/symbolInfo", &ClangdLSPServer::onSymbolInfo); MsgHandler->bind("textDocument/typeHierarchy", &ClangdLSPServer::onTypeHierarchy); + MsgHandler->bind("typeHierarchy/resolve", &ClangdLSPServer::onResolveTypeHierarchy); // clang-format on } diff --git a/clang-tools-extra/clangd/ClangdLSPServer.h b/clang-tools-extra/clangd/ClangdLSPServer.h index 43e05b3dc8e558..1c37750a18526c 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.h +++ b/clang-tools-extra/clangd/ClangdLSPServer.h @@ -100,6 +100,8 @@ class ClangdLSPServer : private DiagnosticsConsumer { Callback>); void onTypeHierarchy(const TypeHierarchyParams &, Callback>); + void onResolveTypeHierarchy(const ResolveTypeHierarchyItemParams &, + Callback>); void onChangeConfiguration(const DidChangeConfigurationParams &); void onSymbolInfo(const TextDocumentPositionParams &, Callback>); diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp index 451dac6f0df4ba..10949ef001c022 100644 --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -528,6 +528,13 @@ void ClangdServer::typeHierarchy(PathRef File, Position Pos, int Resolve, WorkScheduler.runWithAST("Type Hierarchy", File, Bind(Action, std::move(CB))); } +void ClangdServer::resolveTypeHierarchy( + TypeHierarchyItem Item, int Resolve, TypeHierarchyDirection Direction, + Callback> CB) { + clangd::resolveTypeHierarchy(Item, Resolve, Direction, Index); + CB(Item); +} + void ClangdServer::onFileEvent(const DidChangeWatchedFilesParams &Params) { // FIXME: Do nothing for now. This will be used for indexing and potentially // invalidating other caches. diff --git a/clang-tools-extra/clangd/ClangdServer.h b/clang-tools-extra/clangd/ClangdServer.h index ba39806eb72c4c..fa6783b1f1c131 100644 --- a/clang-tools-extra/clangd/ClangdServer.h +++ b/clang-tools-extra/clangd/ClangdServer.h @@ -210,6 +210,11 @@ class ClangdServer { TypeHierarchyDirection Direction, Callback> CB); + /// Resolve type hierarchy item in the given direction. + void resolveTypeHierarchy(TypeHierarchyItem Item, int Resolve, + TypeHierarchyDirection Direction, + Callback> CB); + /// Retrieve the top symbols from the workspace matching a query. void workspaceSymbols(StringRef Query, int Limit, Callback> CB); diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp index 7c70afb567df92..600896b1eeee62 100644 --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -422,8 +422,7 @@ bool fromJSON(const llvm::json::Value &Params, bool fromJSON(const llvm::json::Value &Params, DocumentRangeFormattingParams &R) { llvm::json::ObjectMapper O(Params); - return O && O.map("textDocument", R.textDocument) && - O.map("range", R.range); + return O && O.map("textDocument", R.textDocument) && O.map("range", R.range); } bool fromJSON(const llvm::json::Value &Params, @@ -445,8 +444,8 @@ bool fromJSON(const llvm::json::Value &Params, DocumentSymbolParams &R) { llvm::json::Value toJSON(const DiagnosticRelatedInformation &DRI) { return llvm::json::Object{ - {"location", DRI.location}, - {"message", DRI.message}, + {"location", DRI.location}, + {"message", DRI.message}, }; } @@ -978,6 +977,8 @@ llvm::json::Value toJSON(const TypeHierarchyItem &I) { Result["parents"] = I.parents; if (I.children) Result["children"] = I.children; + if (I.data) + Result["data"] = I.data; return std::move(Result); } @@ -996,10 +997,18 @@ bool fromJSON(const llvm::json::Value &Params, TypeHierarchyItem &I) { O.map("deprecated", I.deprecated); O.map("parents", I.parents); O.map("children", I.children); + O.map("data", I.data); return true; } +bool fromJSON(const llvm::json::Value &Params, + ResolveTypeHierarchyItemParams &P) { + llvm::json::ObjectMapper O(Params); + return O && O.map("item", P.item) && O.map("resolve", P.resolve) && + O.map("direction", P.direction); +} + bool fromJSON(const llvm::json::Value &Params, ReferenceParams &R) { TextDocumentPositionParams &Base = R; return fromJSON(Params, Base); diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h index 7a1a8c77d25919..a2c9438ea9d5d3 100644 --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -1127,7 +1127,7 @@ struct TypeHierarchyItem { SymbolKind kind; /// `true` if the hierarchy item is deprecated. Otherwise, `false`. - bool deprecated; + bool deprecated = false; /// The URI of the text document where this type hierarchy item belongs to. URIForFile uri; @@ -1153,13 +1153,26 @@ struct TypeHierarchyItem { /// descendants. If not defined, the children have not been resolved. llvm::Optional> children; - /// The protocol has a slot here for an optional 'data' filed, which can - /// be used to identify a type hierarchy item in a resolve request. We don't - /// need this (the item itself is sufficient to identify what to resolve) - /// so don't declare it. + /// An optional 'data' filed, which can be used to identify a type hierarchy + /// item in a resolve request. + llvm::Optional data; }; llvm::json::Value toJSON(const TypeHierarchyItem &); llvm::raw_ostream &operator<<(llvm::raw_ostream &, const TypeHierarchyItem &); +bool fromJSON(const llvm::json::Value &, TypeHierarchyItem &); + +/// Parameters for the `typeHierarchy/resolve` request. +struct ResolveTypeHierarchyItemParams { + /// The item to resolve. + TypeHierarchyItem item; + + /// The hierarchy levels to resolve. `0` indicates no level. + int resolve; + + /// The direction of the hierarchy levels to resolve. + TypeHierarchyDirection direction; +}; +bool fromJSON(const llvm::json::Value &, ResolveTypeHierarchyItemParams &); struct ReferenceParams : public TextDocumentPositionParams { // For now, no options like context.includeDeclaration are supported. diff --git a/clang-tools-extra/clangd/QueryDriverDatabase.cpp b/clang-tools-extra/clangd/QueryDriverDatabase.cpp index d71ee3184cf5f4..28596dafb601fd 100644 --- a/clang-tools-extra/clangd/QueryDriverDatabase.cpp +++ b/clang-tools-extra/clangd/QueryDriverDatabase.cpp @@ -58,12 +58,13 @@ namespace { std::vector parseDriverOutput(llvm::StringRef Output) { std::vector SystemIncludes; - constexpr char const *SIS = "#include <...> search starts here:"; + const char SIS[] = "#include <...> search starts here:"; constexpr char const *SIE = "End of search list."; llvm::SmallVector Lines; Output.split(Lines, '\n', /*MaxSplit=*/-1, /*KeepEmpty=*/false); - auto StartIt = std::find(Lines.begin(), Lines.end(), SIS); + auto StartIt = llvm::find_if( + Lines, [SIS](llvm::StringRef Line) { return Line.trim() == SIS; }); if (StartIt == Lines.end()) { elog("System include extraction: start marker not found: {0}", Output); return {}; diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp index 40070a5bbadd25..59fa5319d700d6 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -31,6 +31,14 @@ class HighlightingTokenCollector std::vector collectTokens() { Tokens.clear(); TraverseAST(Ctx); + // Initializer lists can give duplicates of tokens, therefore all tokens + // must be deduplicated. + llvm::sort(Tokens, + [](const HighlightingToken &L, const HighlightingToken &R) { + return std::tie(L.R, L.Kind) < std::tie(R.R, R.Kind); + }); + auto Last = std::unique(Tokens.begin(), Tokens.end()); + Tokens.erase(Last, Tokens.end()); return Tokens; } @@ -40,6 +48,16 @@ class HighlightingTokenCollector return true; } + bool VisitMemberExpr(MemberExpr *ME) { + const auto *MD = ME->getMemberDecl(); + if (isa(MD)) + // When calling the destructor manually like: AAA::~A(); The ~ is a + // MemberExpr. Other methods should still be highlighted though. + return true; + addToken(ME->getMemberLoc(), MD); + return true; + } + bool VisitNamedDecl(NamedDecl *ND) { // UsingDirectiveDecl's namespaces do not show up anywhere else in the // Visit/Traverse mehods. But they should also be highlighted as a @@ -75,6 +93,25 @@ class HighlightingTokenCollector return true; } + bool VisitTypedefNameDecl(TypedefNameDecl *TD) { + if(const auto *TSI = TD->getTypeSourceInfo()) + addTypeLoc(TD->getLocation(), TSI->getTypeLoc()); + return true; + } + + bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc &TL) { + // TemplateTypeParmTypeLoc does not have a TagDecl in its type ptr. + addToken(TL.getBeginLoc(), TL.getDecl()); + return true; + } + + bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc &TL) { + if (const TemplateDecl *TD = + TL.getTypePtr()->getTemplateName().getAsTemplateDecl()) + addToken(TL.getBeginLoc(), TD); + return true; + } + bool VisitTypeLoc(TypeLoc &TL) { // This check is for not getting two entries when there are anonymous // structs. It also makes us not highlight certain namespace qualifiers @@ -83,9 +120,7 @@ class HighlightingTokenCollector if (TL.getTypeLocClass() == TypeLoc::TypeLocClass::Elaborated) return true; - if (const Type *TP = TL.getTypePtr()) - if (const TagDecl *TD = TP->getAsTagDecl()) - addToken(TL.getBeginLoc(), TD); + addTypeLoc(TL.getBeginLoc(), TL); return true; } @@ -100,6 +135,12 @@ class HighlightingTokenCollector } private: + void addTypeLoc(SourceLocation Loc, const TypeLoc &TL) { + if (const Type *TP = TL.getTypePtr()) + if (const TagDecl *TD = TP->getAsTagDecl()) + addToken(Loc, TD); + } + void addToken(SourceLocation Loc, const NamedDecl *D) { if (D->getDeclName().isIdentifier() && D->getName().empty()) // Don't add symbols that don't have any length. @@ -107,6 +148,10 @@ class HighlightingTokenCollector // We highlight class decls, constructor decls and destructor decls as // `Class` type. The destructor decls are handled in `VisitTypeLoc` (we will // visit a TypeLoc where the underlying Type is a CXXRecordDecl). + if (isa(D)) { + addToken(Loc, HighlightingKind::Class); + return; + } if (isa(D)) { addToken(Loc, HighlightingKind::Class); return; @@ -115,10 +160,22 @@ class HighlightingTokenCollector addToken(Loc, HighlightingKind::Class); return; } + if (isa(D)) { + addToken(Loc, HighlightingKind::Method); + return; + } + if (isa(D)) { + addToken(Loc, HighlightingKind::Field); + return; + } if (isa(D)) { addToken(Loc, HighlightingKind::Enum); return; } + if (isa(D)) { + addToken(Loc, HighlightingKind::EnumConstant); + return; + } if (isa(D)) { addToken(Loc, HighlightingKind::Variable); return; @@ -135,6 +192,14 @@ class HighlightingTokenCollector addToken(Loc, HighlightingKind::Namespace); return; } + if (isa(D)) { + addToken(Loc, HighlightingKind::TemplateParameter); + return; + } + if (isa(D)) { + addToken(Loc, HighlightingKind::TemplateParameter); + return; + } } void addToken(SourceLocation Loc, HighlightingKind Kind) { @@ -243,14 +308,22 @@ llvm::StringRef toTextMateScope(HighlightingKind Kind) { switch (Kind) { case HighlightingKind::Function: return "entity.name.function.cpp"; + case HighlightingKind::Method: + return "entity.name.function.method.cpp"; case HighlightingKind::Variable: - return "variable.cpp"; + return "variable.other.cpp"; + case HighlightingKind::Field: + return "variable.other.field.cpp"; case HighlightingKind::Class: return "entity.name.type.class.cpp"; case HighlightingKind::Enum: return "entity.name.type.enum.cpp"; + case HighlightingKind::EnumConstant: + return "variable.other.enummember.cpp"; case HighlightingKind::Namespace: return "entity.name.namespace.cpp"; + case HighlightingKind::TemplateParameter: + return "entity.name.type.template.cpp"; case HighlightingKind::NumKinds: llvm_unreachable("must not pass NumKinds to the function"); } diff --git a/clang-tools-extra/clangd/SemanticHighlighting.h b/clang-tools-extra/clangd/SemanticHighlighting.h index ba160e1c92999c..f38fa46dec3634 100644 --- a/clang-tools-extra/clangd/SemanticHighlighting.h +++ b/clang-tools-extra/clangd/SemanticHighlighting.h @@ -26,9 +26,13 @@ namespace clangd { enum class HighlightingKind { Variable = 0, Function, + Method, + Field, Class, Enum, + EnumConstant, Namespace, + TemplateParameter, NumKinds, }; diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index 1d34499b36edf1..6339f8643f745e 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -893,7 +893,7 @@ llvm::Optional getDeducedType(ParsedAST &AST, /// Retrieves the deduced type at a given location (auto, decltype). bool hasDeducedType(ParsedAST &AST, SourceLocation SourceLocationBeg) { - return (bool) getDeducedType(AST, SourceLocationBeg); + return (bool)getDeducedType(AST, SourceLocationBeg); } llvm::Optional getHover(ParsedAST &AST, Position Pos, @@ -1104,6 +1104,10 @@ symbolToTypeHierarchyItem(const Symbol &S, const SymbolIndex *Index, // (https://github.com/clangd/clangd/issues/59). THI.range = THI.selectionRange; THI.uri = Loc->uri; + // Store the SymbolID in the 'data' field. The client will + // send this back in typeHierarchy/resolve, allowing us to + // continue resolving additional levels of the type hierarchy. + THI.data = S.ID.str(); return std::move(THI); } @@ -1128,15 +1132,9 @@ static void fillSubTypes(const SymbolID &ID, using RecursionProtectionSet = llvm::SmallSet; -static Optional -getTypeAncestors(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, - RecursionProtectionSet &RPSet) { - Optional Result = declToTypeHierarchyItem(ASTCtx, CXXRD); - if (!Result) - return Result; - - Result->parents.emplace(); - +static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, + std::vector &SuperTypes, + RecursionProtectionSet &RPSet) { // typeParents() will replace dependent template specializations // with their class template, so to avoid infinite recursion for // certain types of hierarchies, keep the templates encountered @@ -1145,22 +1143,22 @@ getTypeAncestors(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, auto *Pattern = CXXRD.getDescribedTemplate() ? &CXXRD : nullptr; if (Pattern) { if (!RPSet.insert(Pattern).second) { - return Result; + return; } } for (const CXXRecordDecl *ParentDecl : typeParents(&CXXRD)) { if (Optional ParentSym = - getTypeAncestors(*ParentDecl, ASTCtx, RPSet)) { - Result->parents->emplace_back(std::move(*ParentSym)); + declToTypeHierarchyItem(ASTCtx, *ParentDecl)) { + ParentSym->parents.emplace(); + fillSuperTypes(*ParentDecl, ASTCtx, *ParentSym->parents, RPSet); + SuperTypes.emplace_back(std::move(*ParentSym)); } } if (Pattern) { RPSet.erase(Pattern); } - - return Result; } const CXXRecordDecl *findRecordTypeAt(ParsedAST &AST, Position Pos) { @@ -1227,12 +1225,19 @@ getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels, if (!CXXRD) return llvm::None; - RecursionProtectionSet RPSet; Optional Result = - getTypeAncestors(*CXXRD, AST.getASTContext(), RPSet); + declToTypeHierarchyItem(AST.getASTContext(), *CXXRD); if (!Result) return Result; + if (Direction == TypeHierarchyDirection::Parents || + Direction == TypeHierarchyDirection::Both) { + Result->parents.emplace(); + + RecursionProtectionSet RPSet; + fillSuperTypes(*CXXRD, AST.getASTContext(), *Result->parents, RPSet); + } + if ((Direction == TypeHierarchyDirection::Children || Direction == TypeHierarchyDirection::Both) && ResolveLevels > 0) { @@ -1247,6 +1252,25 @@ getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels, return Result; } +void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels, + TypeHierarchyDirection Direction, + const SymbolIndex *Index) { + // We only support typeHierarchy/resolve for children, because for parents + // we ignore ResolveLevels and return all levels of parents eagerly. + if (Direction == TypeHierarchyDirection::Parents || ResolveLevels == 0) + return; + + Item.children.emplace(); + + if (Index && Item.data) { + // We store the item's SymbolID in the 'data' field, and the client + // passes it back to us in typeHierarchy/resolve. + if (Expected ID = SymbolID::fromStr(*Item.data)) { + fillSubTypes(*ID, *Item.children, Index, ResolveLevels, Item.uri.file()); + } + } +} + FormattedString HoverInfo::present() const { FormattedString Output; if (NamespaceScope) { diff --git a/clang-tools-extra/clangd/XRefs.h b/clang-tools-extra/clangd/XRefs.h index 318133a572a288..3044036c17f158 100644 --- a/clang-tools-extra/clangd/XRefs.h +++ b/clang-tools-extra/clangd/XRefs.h @@ -141,6 +141,10 @@ llvm::Optional getTypeHierarchy( ParsedAST &AST, Position Pos, int Resolve, TypeHierarchyDirection Direction, const SymbolIndex *Index = nullptr, PathRef TUPath = PathRef{}); +void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels, + TypeHierarchyDirection Direction, + const SymbolIndex *Index); + /// Retrieves the deduced type at a given location (auto, decltype). /// Retuns None unless SourceLocationBeg starts an auto/decltype token. /// It will return the underlying type. diff --git a/clang-tools-extra/clangd/index/Background.cpp b/clang-tools-extra/clangd/index/Background.cpp index 458e6fc355f826..23445e16b2f3f3 100644 --- a/clang-tools-extra/clangd/index/Background.cpp +++ b/clang-tools-extra/clangd/index/Background.cpp @@ -127,7 +127,7 @@ BackgroundIndex::BackgroundIndex( BackgroundIndexStorage::Factory IndexStorageFactory, size_t ThreadPoolSize) : SwapIndex(llvm::make_unique()), FSProvider(FSProvider), CDB(CDB), BackgroundContext(std::move(BackgroundContext)), - Rebuilder(this, &IndexedSymbols), + Rebuilder(this, &IndexedSymbols, ThreadPoolSize), IndexStorageFactory(std::move(IndexStorageFactory)), CommandsChanged( CDB.watch([&](const std::vector &ChangedFiles) { diff --git a/clang-tools-extra/clangd/index/BackgroundRebuild.h b/clang-tools-extra/clangd/index/BackgroundRebuild.h index 5a6227e8baab3f..f660957f624199 100644 --- a/clang-tools-extra/clangd/index/BackgroundRebuild.h +++ b/clang-tools-extra/clangd/index/BackgroundRebuild.h @@ -16,6 +16,7 @@ #include "index/FileIndex.h" #include "index/Index.h" +#include "llvm/Support/Threading.h" namespace clang { namespace clangd { @@ -45,12 +46,9 @@ namespace clangd { // This class is exposed in the header so it can be tested. class BackgroundIndexRebuilder { public: - // Thresholds for rebuilding as TUs get indexed. - static constexpr unsigned TUsBeforeFirstBuild = 5; - static constexpr unsigned TUsBeforeRebuild = 100; - - BackgroundIndexRebuilder(SwapIndex *Target, FileSymbols *Source) - : Target(Target), Source(Source) {} + BackgroundIndexRebuilder(SwapIndex *Target, FileSymbols *Source, + unsigned Threads) + : TUsBeforeFirstBuild(Threads), Target(Target), Source(Source) {} // Called to indicate a TU has been indexed. // May rebuild, if enough TUs have been indexed. @@ -71,6 +69,10 @@ class BackgroundIndexRebuilder { // Ensures we won't start any more rebuilds. void shutdown(); + // Thresholds for rebuilding as TUs get indexed. + const unsigned TUsBeforeFirstBuild; // Typically one per worker thread. + const unsigned TUsBeforeRebuild = 100; + private: // Run Check under the lock, and rebuild if it returns true. void maybeRebuild(const char *Reason, std::function Check); diff --git a/clang-tools-extra/clangd/test/semantic-highlighting.test b/clang-tools-extra/clangd/test/semantic-highlighting.test index 810dfe6207e58c..732fb7b7f30b59 100644 --- a/clang-tools-extra/clangd/test/semantic-highlighting.test +++ b/clang-tools-extra/clangd/test/semantic-highlighting.test @@ -5,19 +5,31 @@ # CHECK: "semanticHighlighting": { # CHECK-NEXT: "scopes": [ # CHECK-NEXT: [ -# CHECK-NEXT: "variable.cpp" +# CHECK-NEXT: "variable.other.cpp" # CHECK-NEXT: ], # CHECK-NEXT: [ # CHECK-NEXT: "entity.name.function.cpp" # CHECK-NEXT: ], # CHECK-NEXT: [ +# CHECK-NEXT: "entity.name.function.method.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ +# CHECK-NEXT: "variable.other.field.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ # CHECK-NEXT: "entity.name.type.class.cpp" # CHECK-NEXT: ], # CHECK-NEXT: [ # CHECK-NEXT: "entity.name.type.enum.cpp" # CHECK-NEXT: ], # CHECK-NEXT: [ +# CHECK-NEXT: "variable.other.enummember.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ # CHECK-NEXT: "entity.name.namespace.cpp" +# CHECK-NEXT: ], +# CHECK-NEXT: [ +# CHECK-NEXT: "entity.name.type.template.cpp" # CHECK-NEXT: ] # CHECK-NEXT: ] # CHECK-NEXT: }, diff --git a/clang-tools-extra/clangd/test/system-include-extractor.test b/clang-tools-extra/clangd/test/system-include-extractor.test index 130afbd828c216..8f99db9122a6d4 100644 --- a/clang-tools-extra/clangd/test/system-include-extractor.test +++ b/clang-tools-extra/clangd/test/system-include-extractor.test @@ -5,7 +5,7 @@ # RUN: echo '#!/bin/bash' >> %t.dir/my_driver.sh # RUN: echo '[ "$0" = "%t.dir/my_driver.sh" ] || exit' >> %t.dir/my_driver.sh # RUN: echo 'echo line to ignore >&2' >> %t.dir/my_driver.sh -# RUN: echo 'echo \#include \<...\> search starts here: >&2' >> %t.dir/my_driver.sh +# RUN: echo 'echo -e "#include <...> search starts here:\r" >&2' >> %t.dir/my_driver.sh # RUN: echo 'echo %t.dir/my/dir/ >&2' >> %t.dir/my_driver.sh # RUN: echo 'echo %t.dir/my/dir2/ >&2' >> %t.dir/my_driver.sh # RUN: echo 'echo End of search list. >&2' >> %t.dir/my_driver.sh diff --git a/clang-tools-extra/clangd/test/type-hierarchy.test b/clang-tools-extra/clangd/test/type-hierarchy.test index 7161bd143bff33..b2e78ae249dcc2 100644 --- a/clang-tools-extra/clangd/test/type-hierarchy.test +++ b/clang-tools-extra/clangd/test/type-hierarchy.test @@ -1,7 +1,7 @@ # RUN: clangd -lit-test < %s | FileCheck -strict-whitespace %s {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} --- -{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"struct Parent {};\nstruct Child1 : Parent {};\nstruct Child2 : Child1 {};\nstruct Child3 : Child2 {};"}}} +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"struct Parent {};\nstruct Child1 : Parent {};\nstruct Child2 : Child1 {};\nstruct Child3 : Child2 {};\nstruct Child4 : Child3 {};"}}} --- {"jsonrpc":"2.0","id":1,"method":"textDocument/typeHierarchy","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":2,"character":11},"direction":2,"resolve":1}} # CHECK: "id": 1 @@ -9,6 +9,7 @@ # CHECK-NEXT: "result": { # CHECK-NEXT: "children": [ # CHECK-NEXT: { +# CHECK-NEXT: "data": "A6576FE083F2949A", # CHECK-NEXT: "kind": 23, # CHECK-NEXT: "name": "Child3", # CHECK-NEXT: "range": { @@ -114,6 +115,64 @@ # CHECK-NEXT: "uri": "file:///clangd-test/main.cpp" # CHECK-NEXT: } --- -{"jsonrpc":"2.0","id":2,"method":"shutdown"} +{"jsonrpc":"2.0","id":2,"method":"typeHierarchy/resolve","params":{"item":{"uri":"test:///main.cpp","data":"A6576FE083F2949A","name":"Child3","kind":23,"range":{"end":{"character":13,"line":3},"start":{"character":7,"line":3}},"selectionRange":{"end":{"character":13,"line":3},"start":{"character":7,"line":3}}},"direction":0,"resolve":1}} +# CHECK: "id": 2 +# CHECK-NEXT: "jsonrpc": "2.0", +# CHECK-NEXT: "result": { +# CHECK-NEXT: "children": [ +# CHECK-NEXT: { +# CHECK-NEXT: "data": "5705B382DFC77CBC", +# CHECK-NEXT: "kind": 23, +# CHECK-NEXT: "name": "Child4", +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 4 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 4 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "selectionRange": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 4 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 4 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "uri": "file:///clangd-test/main.cpp" +# CHECK-NEXT: } +# CHECK-NEXT: ], +# CHECK-NEXT: "data": "A6576FE083F2949A", +# CHECK-NEXT: "kind": 23, +# CHECK-NEXT: "name": "Child3", +# CHECK-NEXT: "range": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "selectionRange": { +# CHECK-NEXT: "end": { +# CHECK-NEXT: "character": 13, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: }, +# CHECK-NEXT: "start": { +# CHECK-NEXT: "character": 7, +# CHECK-NEXT: "line": 3 +# CHECK-NEXT: } +# CHECK-NEXT: }, +# CHECK-NEXT: "uri": "file:///clangd-test/main.cpp" +# CHECK-NEXT: } +--- +{"jsonrpc":"2.0","id":3,"method":"shutdown"} --- {"jsonrpc":"2.0","method":"exit"} diff --git a/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp b/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp index 15d064a995ca80..79e081bd678938 100644 --- a/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp +++ b/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp @@ -575,7 +575,8 @@ TEST_F(BackgroundIndexTest, CmdLineHash) { class BackgroundIndexRebuilderTest : public testing::Test { protected: BackgroundIndexRebuilderTest() - : Target(llvm::make_unique()), Rebuilder(&Target, &Source) { + : Target(llvm::make_unique()), + Rebuilder(&Target, &Source, /*Threads=*/10) { // Prepare FileSymbols with TestSymbol in it, for checkRebuild. TestSymbol.ID = SymbolID("foo"); } @@ -610,11 +611,10 @@ class BackgroundIndexRebuilderTest : public testing::Test { }; TEST_F(BackgroundIndexRebuilderTest, IndexingTUs) { - for (unsigned I = 0; I < BackgroundIndexRebuilder::TUsBeforeFirstBuild - 1; - ++I) + for (unsigned I = 0; I < Rebuilder.TUsBeforeFirstBuild - 1; ++I) EXPECT_FALSE(checkRebuild([&] { Rebuilder.indexedTU(); })); EXPECT_TRUE(checkRebuild([&] { Rebuilder.indexedTU(); })); - for (unsigned I = 0; I < BackgroundIndexRebuilder::TUsBeforeRebuild - 1; ++I) + for (unsigned I = 0; I < Rebuilder.TUsBeforeRebuild - 1; ++I) EXPECT_FALSE(checkRebuild([&] { Rebuilder.indexedTU(); })); EXPECT_TRUE(checkRebuild([&] { Rebuilder.indexedTU(); })); } @@ -640,7 +640,7 @@ TEST_F(BackgroundIndexRebuilderTest, LoadingShards) { // No rebuilding for indexed files while loading. Rebuilder.startLoading(); - for (unsigned I = 0; I < 3 * BackgroundIndexRebuilder::TUsBeforeRebuild; ++I) + for (unsigned I = 0; I < 3 * Rebuilder.TUsBeforeRebuild; ++I) EXPECT_FALSE(checkRebuild([&] { Rebuilder.indexedTU(); })); // But they get indexed when we're done, even if no shards were loaded. EXPECT_TRUE(checkRebuild([&] { Rebuilder.doneLoading(); })); diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp index f45c11566836e0..2943780b8bdf12 100644 --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -37,7 +37,11 @@ void checkHighlightings(llvm::StringRef Code) { {HighlightingKind::Function, "Function"}, {HighlightingKind::Class, "Class"}, {HighlightingKind::Enum, "Enum"}, - {HighlightingKind::Namespace, "Namespace"}}; + {HighlightingKind::Namespace, "Namespace"}, + {HighlightingKind::EnumConstant, "EnumConstant"}, + {HighlightingKind::Field, "Field"}, + {HighlightingKind::Method, "Method"}, + {HighlightingKind::TemplateParameter, "TemplateParameter"}}; std::vector ExpectedTokens; for (const auto &KindString : KindToString) { std::vector Toks = makeHighlightingTokens( @@ -53,14 +57,14 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { const char *TestCases[] = { R"cpp( struct $Class[[AS]] { - double SomeMember; + double $Field[[SomeMember]]; }; struct { } $Variable[[S]]; void $Function[[foo]](int $Variable[[A]], $Class[[AS]] $Variable[[As]]) { auto $Variable[[VeryLongVariableName]] = 12312; $Class[[AS]] $Variable[[AA]]; - auto $Variable[[L]] = $Variable[[AA]].SomeMember + $Variable[[A]]; + auto $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]]; auto $Variable[[FN]] = [ $Variable[[AA]]](int $Variable[[A]]) -> void {}; $Variable[[FN]](12312); } @@ -72,27 +76,27 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { auto $Variable[[Bou]] = $Function[[Gah]]; } struct $Class[[A]] { - void $Function[[abc]](); + void $Method[[abc]](); }; )cpp", R"cpp( namespace $Namespace[[abc]] { - template + template struct $Class[[A]] { - T t; + $TemplateParameter[[T]] $Field[[t]]; }; } - template - struct $Class[[C]] : $Namespace[[abc]]::A { - typename T::A* D; + template + struct $Class[[C]] : $Namespace[[abc]]::$Class[[A]]<$TemplateParameter[[T]]> { + typename $TemplateParameter[[T]]::A* $Field[[D]]; }; $Namespace[[abc]]::$Class[[A]] $Variable[[AA]]; - typedef $Namespace[[abc]]::$Class[[A]] AAA; + typedef $Namespace[[abc]]::$Class[[A]] $Class[[AAA]]; struct $Class[[B]] { $Class[[B]](); ~$Class[[B]](); void operator<<($Class[[B]]); - $Class[[AAA]] AA; + $Class[[AAA]] $Field[[AA]]; }; $Class[[B]]::$Class[[B]]() {} $Class[[B]]::~$Class[[B]]() {} @@ -103,12 +107,19 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { } )cpp", R"cpp( - enum class $Enum[[E]] {}; - enum $Enum[[EE]] {}; + enum class $Enum[[E]] { + $EnumConstant[[A]], + $EnumConstant[[B]], + }; + enum $Enum[[EE]] { + $EnumConstant[[Hi]], + }; struct $Class[[A]] { - $Enum[[E]] EEE; - $Enum[[EE]] EEEE; + $Enum[[E]] $Field[[EEE]]; + $Enum[[EE]] $Field[[EEEE]]; }; + int $Variable[[I]] = $EnumConstant[[Hi]]; + $Enum[[E]] $Variable[[L]] = $Enum[[E]]::$EnumConstant[[B]]; )cpp", R"cpp( namespace $Namespace[[abc]] { @@ -118,7 +129,7 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { namespace $Namespace[[cde]] { struct $Class[[A]] { enum class $Enum[[B]] { - Hi, + $EnumConstant[[Hi]], }; }; } @@ -129,9 +140,79 @@ TEST(SemanticHighlighting, GetsCorrectTokens) { $Namespace[[abc]]::$Namespace[[bcd]]::$Namespace[[cde]]; $Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable[[AA]]; $Namespace[[vwz]]::$Class[[A]]::$Enum[[B]] $Variable[[AAA]] = - $Namespace[[vwz]]::$Class[[A]]::$Enum[[B]]::Hi; + $Namespace[[vwz]]::$Class[[A]]::$Enum[[B]]::$EnumConstant[[Hi]]; ::$Namespace[[vwz]]::$Class[[A]] $Variable[[B]]; ::$Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable[[BB]]; + )cpp", + R"cpp( + struct $Class[[D]] { + double $Field[[C]]; + }; + struct $Class[[A]] { + double $Field[[B]]; + $Class[[D]] $Field[[E]]; + static double $Variable[[S]]; + void $Method[[foo]]() { + $Field[[B]] = 123; + this->$Field[[B]] = 156; + this->$Method[[foo]](); + $Method[[foo]](); + $Variable[[S]] = 90.1; + } + }; + void $Function[[foo]]() { + $Class[[A]] $Variable[[AA]]; + $Variable[[AA]].$Field[[B]] += 2; + $Variable[[AA]].$Method[[foo]](); + $Variable[[AA]].$Field[[E]].$Field[[C]]; + $Class[[A]]::$Variable[[S]] = 90; + } + )cpp", + R"cpp( + struct $Class[[AA]] { + int $Field[[A]]; + } + int $Variable[[B]]; + $Class[[AA]] $Variable[[A]]{$Variable[[B]]}; + )cpp", + R"cpp( + namespace $Namespace[[a]] { + struct $Class[[A]] {}; + } + typedef $Namespace[[a]]::$Class[[A]] $Class[[B]]; + using $Class[[BB]] = $Namespace[[a]]::$Class[[A]]; + enum class $Enum[[E]] {}; + typedef $Enum[[E]] $Enum[[C]]; + typedef $Enum[[C]] $Enum[[CC]]; + using $Enum[[CD]] = $Enum[[CC]]; + $Enum[[CC]] $Function[[f]]($Class[[B]]); + $Enum[[CD]] $Function[[f]]($Class[[BB]]); + )cpp", + R"cpp( + template + class $Class[[A]] { + $TemplateParameter[[T]] $Field[[AA]]; + $TemplateParameter[[T]] $Method[[foo]](); + }; + template + class $Class[[B]] { + $Class[[A]]<$TemplateParameter[[TT]]> $Field[[AA]]; + }; + template + class $Class[[BB]] {}; + template + class $Class[[BB]]<$TemplateParameter[[T]], int> {}; + template + class $Class[[BB]]<$TemplateParameter[[T]], $TemplateParameter[[T]]*> {}; + + template class $TemplateParameter[[T]], class $TemplateParameter[[C]]> + $TemplateParameter[[T]]<$TemplateParameter[[C]]> $Function[[f]](); + + template + class $Class[[Foo]] {}; + + template + void $Function[[foo]]($TemplateParameter[[T]] ...); )cpp"}; for (const auto &TestCase : TestCases) { checkHighlightings(TestCase); diff --git a/clang-tools-extra/clangd/unittests/TestTU.cpp b/clang-tools-extra/clangd/unittests/TestTU.cpp index 4747f5ea2e3d6d..7e77160870663d 100644 --- a/clang-tools-extra/clangd/unittests/TestTU.cpp +++ b/clang-tools-extra/clangd/unittests/TestTU.cpp @@ -38,6 +38,10 @@ ParsedAST TestTU::build() const { Cmd.push_back("-include"); Cmd.push_back(ImplicitHeaderGuard ? ImportThunk.c_str() : FullHeaderName.c_str()); + // ms-compatibility changes the meaning of #import. + // The default is OS-dependent (on on windows), ensure it's off. + if (ImplicitHeaderGuard) + Cmd.push_back("-fno-ms-compatibility"); } Cmd.insert(Cmd.end(), ExtraArgs.begin(), ExtraArgs.end()); // Put the file name at the end -- this allows the extra arg (-xc++) to diff --git a/clang-tools-extra/clangd/unittests/TweakTests.cpp b/clang-tools-extra/clangd/unittests/TweakTests.cpp index 7a0d88405b4f27..69f74e9d41b970 100644 --- a/clang-tools-extra/clangd/unittests/TweakTests.cpp +++ b/clang-tools-extra/clangd/unittests/TweakTests.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include "llvm/Testing/Support/Error.h" +#include "gmock/gmock-matchers.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include @@ -134,10 +135,9 @@ void checkApplyContainsError(llvm::StringRef ID, llvm::StringRef Input, auto Result = apply(ID, Input); ASSERT_FALSE(Result) << "expected error message:\n " << ErrorMessage << "\non input:" << Input; - EXPECT_NE(std::string::npos, - llvm::toString(Result.takeError()).find(ErrorMessage)) - << "Wrong error message:\n " << llvm::toString(Result.takeError()) - << "\nexpected:\n " << ErrorMessage; + EXPECT_THAT(llvm::toString(Result.takeError()), + testing::HasSubstr(ErrorMessage)) + << Input; } TEST(TweakTest, SwapIfBranches) { diff --git a/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp b/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp index be16646a72036d..cebfa8dfbeb93c 100644 --- a/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp +++ b/clang-tools-extra/clangd/unittests/TypeHierarchyTests.cpp @@ -42,8 +42,17 @@ MATCHER_P(WithKind, Kind, "") { return arg.kind == Kind; } MATCHER_P(SelectionRangeIs, R, "") { return arg.selectionRange == R; } template ::testing::Matcher Parents(ParentMatchers... ParentsM) { - return Field(&TypeHierarchyItem::parents, HasValue(ElementsAre(ParentsM...))); + return Field(&TypeHierarchyItem::parents, + HasValue(UnorderedElementsAre(ParentsM...))); } +template +::testing::Matcher Children(ChildMatchers... ChildrenM) { + return Field(&TypeHierarchyItem::children, + HasValue(UnorderedElementsAre(ChildrenM...))); +} +// Note: "not resolved" is differnt from "resolved but empty"! +MATCHER(ParentsNotResolved, "") { return !arg.parents; } +MATCHER(ChildrenNotResolved, "") { return !arg.children; } TEST(FindRecordTypeAt, TypeOrVariable) { Annotations Source(R"cpp( @@ -603,6 +612,42 @@ struct Child : Parent {}; EXPECT_THAT(collectSubtypes(Parent, Index.get()), ElementsAre(Child)); } +TEST(Subtypes, LazyResolution) { + Annotations Source(R"cpp( +struct P^arent {}; +struct Child1 : Parent {}; +struct Child2a : Child1 {}; +struct Child2b : Child1 {}; +)cpp"); + + TestTU TU = TestTU::withCode(Source.code()); + auto AST = TU.build(); + auto Index = TU.index(); + + llvm::Optional Result = getTypeHierarchy( + AST, Source.point(), /*ResolveLevels=*/1, + TypeHierarchyDirection::Children, Index.get(), testPath(TU.Filename)); + ASSERT_TRUE(bool(Result)); + EXPECT_THAT( + *Result, + AllOf(WithName("Parent"), WithKind(SymbolKind::Struct), + ParentsNotResolved(), + Children(AllOf(WithName("Child1"), WithKind(SymbolKind::Struct), + ParentsNotResolved(), ChildrenNotResolved())))); + + resolveTypeHierarchy((*Result->children)[0], /*ResolveLevels=*/1, + TypeHierarchyDirection::Children, Index.get()); + + EXPECT_THAT( + (*Result->children)[0], + AllOf(WithName("Child1"), WithKind(SymbolKind::Struct), + ParentsNotResolved(), + Children(AllOf(WithName("Child2a"), WithKind(SymbolKind::Struct), + ParentsNotResolved(), ChildrenNotResolved()), + AllOf(WithName("Child2b"), WithKind(SymbolKind::Struct), + ParentsNotResolved(), ChildrenNotResolved())))); +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index edc158499dcbdd..0f52c53d443c30 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -57,7 +57,7 @@ The improvements are... Improvements to clang-query --------------------------- -- ... +The improvements are... Improvements to clang-rename ---------------------------- @@ -109,14 +109,7 @@ Improvements to clang-tidy - New :doc:`android-cloexec-pipe2 ` check. - This checks ensures that ``pipe2()`` is called with the O_CLOEXEC flag. - -- New :doc:`bugprone-unhandled-self-assignment - ` check. - - Finds user-defined copy assignment operators which do not protect the code - against self-assignment either by checking self-assignment explicitly or - using the copy-and-swap or the copy-and-move method. + This checks ensures that ``pipe2()`` is called with the ``O_CLOEXEC`` flag. - New :doc:`bugprone-branch-clone ` check. @@ -131,6 +124,13 @@ Improvements to clang-tidy Checks if any calls to POSIX functions (except ``posix_openpt``) expect negative return values. +- New :doc:`bugprone-unhandled-self-assignment + ` check. + + Finds user-defined copy assignment operators which do not protect the code + against self-assignment either by checking self-assignment explicitly or + using the copy-and-swap or the copy-and-move method. + - New :doc:`fuchsia-default-arguments-calls ` check. @@ -138,13 +138,19 @@ Improvements to clang-tidy This was previously done by `fuchsia-default-arguments check`, which has been removed. -- New :doc:`fuchsia-default-arguments-calls - ` check. +- New :doc:`fuchsia-default-arguments-declarations + ` check. Warns if a function or method is declared with default parameters. This was previously done by `fuchsia-default-arguments check` check, which has been removed. +- New :doc:`google-objc-avoid-nsobject-new + ` check. + + Checks for calls to ``+new`` or overrides of it, which are prohibited by the + Google Objective-C style guide. + - New :doc:`google-readability-avoid-underscore-in-googletest-name ` check. @@ -152,11 +158,19 @@ Improvements to clang-tidy Checks whether there are underscores in googletest test and test case names in test macros, which is prohibited by the Googletest FAQ. -- New :doc:`google-objc-avoid-nsobject-new - ` check. +- New :doc:`llvm-prefer-isa-or-dyn-cast-in-conditionals + ` check. - Checks for calls to ``+new`` or overrides of it, which are prohibited by the - Google Objective-C style guide. + Looks at conditionals and finds and replaces cases of ``cast<>``, + which will assert rather than return a null pointer, and + ``dyn_cast<>`` where the return value is not captured. Additionally, + finds and replaces cases that match the pattern ``var && + isa(var)``, where ``var`` is evaluated twice. + +- New :doc:`modernize-use-trailing-return-type + ` check. + + Rewrites function signatures to use a trailing return type. - New :doc:`objc-super-self ` check. @@ -164,6 +178,24 @@ Improvements to clang-tidy subclasses of ``NSObject`` and recommends calling a superclass initializer instead. +- New :doc:`openmp-exception-escape + ` check. + + Analyzes OpenMP Structured Blocks and checks that no exception escapes + out of the Structured Block it was thrown in. + +- New :doc:`openmp-use-default-none + ` check. + + Finds OpenMP directives that are allowed to contain a ``default`` clause, + but either don't specify it or the clause is specified but with the kind + other than ``none``, and suggests to use the ``default(none)`` clause. + +- New :doc:`readability-convert-member-functions-to-static + ` check. + + Finds non-static member functions that can be made ``static``. + - New alias :doc:`cert-oop54-cpp ` to :doc:`bugprone-unhandled-self-assignment @@ -186,65 +218,41 @@ Improvements to clang-tidy which greatly reduces warnings related to loops which are unlikely to cause an actual functional bug. -- The ‘fuchsia-default-arguments’ check has been removed. +- Added `UseAssignment` option to :doc:`cppcoreguidelines-pro-type-member-init + ` + + If set to true, the check will provide fix-its with literal initializers + (``int i = 0;``) instead of curly braces (``int i{};``). + +- The `fuchsia-default-arguments` check has been removed. Warnings of function or method calls and declarations with default arguments were moved to :doc:`fuchsia-default-arguments-calls ` and - :doc:`fuchsia-default-arguments-calls - ` checks respectively. + :doc:`fuchsia-default-arguments-declarations + ` checks + respectively. - The :doc:`google-runtime-int ` check has been disabled in Objective-C++. -- The `Acronyms` and `IncludeDefaultAcronyms` options for the - :doc:`objc-property-declaration ` - check have been removed. - - The :doc:`modernize-use-override ` now supports `OverrideSpelling` and `FinalSpelling` options. -- New :doc:`llvm-prefer-isa-or-dyn-cast-in-conditionals - ` check. - - Looks at conditionals and finds and replaces cases of ``cast<>``, - which will assert rather than return a null pointer, and - ``dyn_cast<>`` where the return value is not captured. Additionally, - finds and replaces cases that match the pattern ``var && - isa(var)``, where ``var`` is evaluated twice. - -- New :doc:`modernize-use-trailing-return-type - ` check. - - Rewrites function signatures to use a trailing return type. - - The :doc:`misc-throw-by-value-catch-by-reference ` now supports `WarnOnLargeObject` and `MaxSize` options to warn on any large trivial object caught by value. -- Added `UseAssignment` option to :doc:`cppcoreguidelines-pro-type-member-init - ` - - If set to true, the check will provide fix-its with literal initializers - (``int i = 0;``) instead of curly braces (``int i{};``). +- The `Acronyms` and `IncludeDefaultAcronyms` options for the + :doc:`objc-property-declaration ` + check have been removed. Improvements to include-fixer ----------------------------- -- New :doc:`openmp-exception-escape - ` check. - - Analyzes OpenMP Structured Blocks and checks that no exception escapes - out of the Structured Block it was thrown in. - -- New :doc:`openmp-use-default-none - ` check. - - Finds OpenMP directives that are allowed to contain a ``default`` clause, - but either don't specify it or the clause is specified but with the kind - other than ``none``, and suggests to use the ``default(none)`` clause. +The improvements are... Improvements to clang-include-fixer ----------------------------------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index f0349b9a90e9e6..27521c86e9676e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -257,6 +257,7 @@ Clang-Tidy Checks readability-braces-around-statements readability-const-return-type readability-container-size-empty + readability-convert-member-functions-to-static readability-delete-null-pointer readability-deleted-default readability-else-after-return diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-convert-member-functions-to-static.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-convert-member-functions-to-static.rst new file mode 100644 index 00000000000000..891f6be6371426 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-convert-member-functions-to-static.rst @@ -0,0 +1,14 @@ +.. title:: clang-tidy - readability-convert-member-functions-to-static + +readability-convert-member-functions-to-static +============================================== + +Finds non-static member functions that can be made ``static`` +because the functions don't use ``this``. + +After applying modifications as suggested by the check, runnnig the check again +might find more opportunities to mark member functions ``static``. + +After making a member function ``static``, you might want to run the check +`readability-static-accessed-through-instance` to replace calls like +``Instance.method()`` by ``Class::method()``. diff --git a/clang-tools-extra/docs/clangd/Features.rst b/clang-tools-extra/docs/clangd/Features.rst index 3e6e745a691c85..87b6713c44acee 100644 --- a/clang-tools-extra/docs/clangd/Features.rst +++ b/clang-tools-extra/docs/clangd/Features.rst @@ -261,7 +261,7 @@ developed outside clangd or become clangd extensions to LSP. +-------------------------------------+------------+----------+ | Call hierarchy | No | No | +-------------------------------------+------------+----------+ -| Type hierarchy | No | No | +| Type hierarchy | No | Yes | +-------------------------------------+------------+----------+ | Organize Includes | No | No | +-------------------------------------+------------+----------+ diff --git a/clang-tools-extra/docs/clangd/Installation.rst b/clang-tools-extra/docs/clangd/Installation.rst index 1552efce1e6272..caf49a75d11056 100644 --- a/clang-tools-extra/docs/clangd/Installation.rst +++ b/clang-tools-extra/docs/clangd/Installation.rst @@ -324,7 +324,7 @@ symlink it (or copy it) to the root of your source tree, if they are different. :: - $ ln -s ~/myproject/compile_commands.json ~/myproject-build/ + $ ln -s ~/myproject-build/compile_commands.json ~/myproject/ :raw-html:`` diff --git a/clang-tools-extra/modularize/Modularize.cpp b/clang-tools-extra/modularize/Modularize.cpp index 59fc5c351ff277..866356d055b620 100644 --- a/clang-tools-extra/modularize/Modularize.cpp +++ b/clang-tools-extra/modularize/Modularize.cpp @@ -369,7 +369,7 @@ getModularizeArgumentsAdjuster(DependencyMap &Dependencies) { // Ignore warnings. (Insert after "clang_tool" at beginning.) NewArgs.insert(NewArgs.begin() + 1, "-w"); // Since we are compiling .h files, assume C++ unless given a -x option. - if (std::find(NewArgs.begin(), NewArgs.end(), "-x") == NewArgs.end()) { + if (!llvm::is_contained(NewArgs, "-x")) { NewArgs.insert(NewArgs.begin() + 2, "-x"); NewArgs.insert(NewArgs.begin() + 3, "c++"); } diff --git a/clang-tools-extra/test/clang-tidy/bugprone-branch-clone-macro-crash.c b/clang-tools-extra/test/clang-tidy/bugprone-branch-clone-macro-crash.c new file mode 100644 index 00000000000000..ce0c0137d0a379 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/bugprone-branch-clone-macro-crash.c @@ -0,0 +1,14 @@ +// RUN: %check_clang_tidy %s bugprone-branch-clone %t +int x = 0; +int y = 1; +#define a(b, c) \ + typeof(b) d; \ + if (b) \ + d = b; \ + else if (c) \ + d = b; + +f() { + // CHECK-MESSAGES: warning: repeated branch in conditional chain [bugprone-branch-clone] + a(x, y) +} diff --git a/clang-tools-extra/test/clang-tidy/fuchsia-multiple-inheritance.cpp b/clang-tools-extra/test/clang-tidy/fuchsia-multiple-inheritance.cpp index fd2ed145c12b46..c7869761cf85e1 100644 --- a/clang-tools-extra/test/clang-tidy/fuchsia-multiple-inheritance.cpp +++ b/clang-tools-extra/test/clang-tidy/fuchsia-multiple-inheritance.cpp @@ -41,6 +41,9 @@ class Interface_with_A_Parent : public Base_A { virtual int baz() = 0; }; +// Shouldn't warn on forward declarations. +class Bad_Child1; + // Inherits from multiple concrete classes. // CHECK-MESSAGES: [[@LINE+2]]:1: warning: inheriting mulitple classes that aren't pure virtual is discouraged [fuchsia-multiple-inheritance] // CHECK-NEXT: class Bad_Child1 : public Base_A, Base_B {}; diff --git a/clang-tools-extra/test/clang-tidy/google-readability-namespace-comments.cpp b/clang-tools-extra/test/clang-tidy/google-readability-namespace-comments.cpp index 9abb984bcbf79c..591c9dae5a74ed 100644 --- a/clang-tools-extra/test/clang-tidy/google-readability-namespace-comments.cpp +++ b/clang-tools-extra/test/clang-tidy/google-readability-namespace-comments.cpp @@ -7,9 +7,9 @@ namespace n2 { void f(); // So that the namespace isn't empty. -// CHECK-MESSAGES: :[[@LINE+4]]:2: warning: namespace 'n2' not terminated with a closing comment [google-readability-namespace-comments] +// CHECK-MESSAGES: :[[@LINE+4]]:1: warning: namespace 'n2' not terminated with a closing comment [google-readability-namespace-comments] // CHECK-MESSAGES: :[[@LINE-7]]:11: note: namespace 'n2' starts here -// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: namespace 'n1' not terminated with +// CHECK-MESSAGES: :[[@LINE+2]]:2: warning: namespace 'n1' not terminated with // CHECK-MESSAGES: :[[@LINE-10]]:11: note: namespace 'n1' starts here }} // CHECK-FIXES: } // namespace n2 @@ -25,7 +25,7 @@ void f(); // So that the namespace isn't empty. // 5 // 6 // 7 -// CHECK-MESSAGES: :[[@LINE+2]]:2: warning: namespace 'macro_expansion' not terminated with +// CHECK-MESSAGES: :[[@LINE+2]]:1: warning: namespace 'macro_expansion' not terminated with // CHECK-MESSAGES: :[[@LINE-10]]:11: note: namespace 'macro_expansion' starts here } // CHECK-FIXES: } // namespace macro_expansion diff --git a/clang-tools-extra/test/clang-tidy/google-readability-nested-namespace-comments.cpp b/clang-tools-extra/test/clang-tidy/google-readability-nested-namespace-comments.cpp index d7765c63820d11..017081d2e95208 100644 --- a/clang-tools-extra/test/clang-tidy/google-readability-nested-namespace-comments.cpp +++ b/clang-tools-extra/test/clang-tidy/google-readability-nested-namespace-comments.cpp @@ -7,9 +7,9 @@ namespace n3 { void f(); -// CHECK-MESSAGES: :[[@LINE+4]]:2: warning: namespace 'n3' not terminated with +// CHECK-MESSAGES: :[[@LINE+4]]:1: warning: namespace 'n3' not terminated with // CHECK-MESSAGES: :[[@LINE-7]]:11: note: namespace 'n3' starts here -// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: namespace 'n1::n2' not terminated with a closing comment [google-readability-namespace-comments] +// CHECK-MESSAGES: :[[@LINE+2]]:2: warning: namespace 'n1::n2' not terminated with a closing comment [google-readability-namespace-comments] // CHECK-MESSAGES: :[[@LINE-10]]:11: note: namespace 'n1::n2' starts here }} // CHECK-FIXES: } // namespace n3 diff --git a/clang-tools-extra/test/clang-tidy/readability-convert-member-functions-to-static.cpp b/clang-tools-extra/test/clang-tidy/readability-convert-member-functions-to-static.cpp new file mode 100644 index 00000000000000..9612fa9de8c204 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/readability-convert-member-functions-to-static.cpp @@ -0,0 +1,218 @@ +// RUN: %check_clang_tidy %s readability-convert-member-functions-to-static %t + +class DoNotMakeEmptyStatic { + void emptyMethod() {} + void empty_method_out_of_line(); +}; + +void DoNotMakeEmptyStatic::empty_method_out_of_line() {} + +class A { + int field; + const int const_field; + static int static_field; + + void no_use() { + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'no_use' can be made static + // CHECK-FIXES: {{^}} static void no_use() { + int i = 1; + } + + int read_field() { + return field; + } + + void write_field() { + field = 1; + } + + int call_non_const_member() { return read_field(); } + + int call_static_member() { + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'call_static_member' can be made static + // CHECK-FIXES: {{^}} static int call_static_member() { + already_static(); + } + + int read_static() { + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'read_static' can be made static + // CHECK-FIXES: {{^}} static int read_static() { + return static_field; + } + void write_static() { + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'write_static' can be made static + // CHECK-FIXES: {{^}} static void write_static() { + static_field = 1; + } + + static int already_static() { return static_field; } + + int already_const() const { return field; } + + int already_const_convert_to_static() const { + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'already_const_convert_to_static' can be made static + // CHECK-FIXES: {{^}} static int already_const_convert_to_static() { + return static_field; + } + + static int out_of_line_already_static(); + + void out_of_line_call_static(); + // CHECK-FIXES: {{^}} static void out_of_line_call_static(); + int out_of_line_const_to_static() const; + // CHECK-FIXES: {{^}} static int out_of_line_const_to_static() ; +}; + +int A::out_of_line_already_static() { return 0; } + +void A::out_of_line_call_static() { + // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: method 'out_of_line_call_static' can be made static + // CHECK-FIXES: {{^}}void A::out_of_line_call_static() { + already_static(); +} + +int A::out_of_line_const_to_static() const { + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'out_of_line_const_to_static' can be made static + // CHECK-FIXES: {{^}}int A::out_of_line_const_to_static() { + return 0; +} + +struct KeepVirtual { + virtual int f() { return 0; } + virtual int h() const { return 0; } +}; + +struct KeepVirtualDerived : public KeepVirtual { + int f() { return 0; } + int h() const override { return 0; } +}; + +// Don't add 'static' to special member functions and operators. +struct KeepSpecial { + KeepSpecial() { int L = 0; } + ~KeepSpecial() { int L = 0; } + int operator+() { return 0; } + operator int() { return 0; } +}; + +void KeepLambdas() { + using FT = int (*)(); + auto F = static_cast([]() { return 0; }); + auto F2 = []() { return 0; }; +} + +template +struct KeepWithTemplateBase : public Base { + int i; + // We cannot make these methods static because they might need to override + // a function from Base. + int static_f() { return 0; } +}; + +template +struct KeepTemplateClass { + int i; + // We cannot make these methods static because a specialization + // might use *this differently. + int static_f() { return 0; } +}; + +struct KeepTemplateMethod { + int i; + // We cannot make these methods static because a specialization + // might use *this differently. + template + static int static_f() { return 0; } +}; + +void instantiate() { + struct S {}; + KeepWithTemplateBase I1; + I1.static_f(); + + KeepTemplateClass I2; + I2.static_f(); + + KeepTemplateMethod I3; + I3.static_f(); +} + +struct Trailing { + auto g() const -> int { + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'g' can be made static + // CHECK-FIXES: {{^}} static auto g() -> int { + return 0; + } + + void vol() volatile { + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'vol' can be made static + return; + } + + void ref() const & { + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'ref' can be made static + return; + } + void refref() const && { + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'refref' can be made static + return; + } + + void restr() __restrict { + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'restr' can be made static + return; + } +}; + +struct UnevaluatedContext { + void f() { sizeof(this); } + + void noex() noexcept(noexcept(this)); +}; + +struct LambdaCapturesThis { + int Field; + + int explicitCapture() { + return [this]() { return Field; }(); + } + + int implicitCapture() { + return [&]() { return Field; }(); + } +}; + +struct NoFixitInMacro { +#define CONST const + int no_use_macro_const() CONST { + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'no_use_macro_const' can be made static + return 0; + } + +#define ADD_CONST(F) F const + int ADD_CONST(no_use_macro2()) { + return 0; + } + +#define FUN no_use_macro() + int i; + int FUN { + return i; + } + +#define T(FunctionName, Keyword) \ + Keyword int FunctionName() { return 0; } +#define EMPTY + T(A, EMPTY) + T(B, static) + +#define T2(FunctionName) \ + int FunctionName() { return 0; } + T2(A2) + +#define VOLATILE volatile + void volatileMacro() VOLATILE { + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'volatileMacro' can be made static + return; + } +}; diff --git a/clang-tools-extra/test/clang-tidy/select-checks.cpp b/clang-tools-extra/test/clang-tidy/select-checks.cpp index 791def75b18bc0..46bf43ca0c3d99 100644 --- a/clang-tools-extra/test/clang-tidy/select-checks.cpp +++ b/clang-tools-extra/test/clang-tidy/select-checks.cpp @@ -5,7 +5,7 @@ namespace i { } -// CHECK: :[[@LINE-1]]:2: warning: namespace 'i' not terminated with a closing comment [llvm-namespace-comment] +// CHECK: :[[@LINE-1]]:1: warning: namespace 'i' not terminated with a closing comment [llvm-namespace-comment] // Expect no warnings from the google-explicit-constructor check: class A { A(int i); }; diff --git a/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp index e95ceb878a68a0..eabc6d45fe5812 100644 --- a/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp @@ -79,10 +79,11 @@ TEST(HTMLGeneratorTest, emitRecordHTML) { I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"}); I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"}); + SmallString<16> PathTo; + llvm::sys::path::native("path/to", PathTo); I.Members.emplace_back("int", "X/Y", "X", AccessSpecifier::AS_private); I.TagType = TagTypeKind::TTK_Class; - I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, - llvm::SmallString<128>("path/to")); + I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, PathTo); I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record); I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record); @@ -97,6 +98,10 @@ TEST(HTMLGeneratorTest, emitRecordHTML) { llvm::raw_string_ostream Actual(Buffer); auto Err = G->generateDocForInfo(&I, Actual); assert(!Err); + SmallString<16> PathToF; + llvm::sys::path::native("../../../path/to/F.html", PathToF); + SmallString<16> PathToInt; + llvm::sys::path::native("../int.html", PathToInt); std::string Expected = R"raw( class r @@ -107,12 +112,14 @@ TEST(HTMLGeneratorTest, emitRecordHTML) {

Inherits from - F + F , G

Members

    -
  • private int X
  • +
  • private int X

Records

    @@ -143,8 +150,10 @@ TEST(HTMLGeneratorTest, emitFunctionHTML) { I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"}); I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"}); - I.ReturnType = TypeInfo(EmptySID, "float", InfoType::IT_default, "path/to"); - I.Params.emplace_back("int", "path/to", "P"); + SmallString<16> PathTo; + llvm::sys::path::native("path/to", PathTo); + I.ReturnType = TypeInfo(EmptySID, "float", InfoType::IT_default, PathTo); + I.Params.emplace_back("int", PathTo, "P"); I.IsMethod = true; I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record); @@ -154,15 +163,21 @@ TEST(HTMLGeneratorTest, emitFunctionHTML) { llvm::raw_string_ostream Actual(Buffer); auto Err = G->generateDocForInfo(&I, Actual); assert(!Err); + SmallString<16> PathToFloat; + llvm::sys::path::native("path/to/float.html", PathToFloat); + SmallString<16> PathToInt; + llvm::sys::path::native("path/to/int.html", PathToInt); std::string Expected = R"raw(

    f

    - float + float f( - int + int P)

    diff --git a/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp b/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp index 5547f98ffd030d..67f1dfdf029eca 100644 --- a/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/ClangTidyDiagnosticConsumerTest.cpp @@ -1,94 +1,94 @@ -#include "ClangTidy.h" -#include "ClangTidyTest.h" -#include "gtest/gtest.h" - -namespace clang { -namespace tidy { -namespace test { - -class TestCheck : public ClangTidyCheck { -public: - TestCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} - void registerMatchers(ast_matchers::MatchFinder *Finder) override { - Finder->addMatcher(ast_matchers::varDecl().bind("var"), this); - } - void check(const ast_matchers::MatchFinder::MatchResult &Result) override { - const auto *Var = Result.Nodes.getNodeAs("var"); - // Add diagnostics in the wrong order. - diag(Var->getLocation(), "variable"); - diag(Var->getTypeSpecStartLoc(), "type specifier"); - } -}; - -TEST(ClangTidyDiagnosticConsumer, SortsErrors) { - std::vector Errors; - runCheckOnCode("int a;", &Errors); - EXPECT_EQ(2ul, Errors.size()); - EXPECT_EQ("type specifier", Errors[0].Message.Message); - EXPECT_EQ("variable", Errors[1].Message.Message); -} - -TEST(GlobList, Empty) { - GlobList Filter(""); - - EXPECT_TRUE(Filter.contains("")); - EXPECT_FALSE(Filter.contains("aaa")); -} - -TEST(GlobList, Nothing) { - GlobList Filter("-*"); - - EXPECT_FALSE(Filter.contains("")); - EXPECT_FALSE(Filter.contains("a")); - EXPECT_FALSE(Filter.contains("-*")); - EXPECT_FALSE(Filter.contains("-")); - EXPECT_FALSE(Filter.contains("*")); -} - -TEST(GlobList, Everything) { - GlobList Filter("*"); - - EXPECT_TRUE(Filter.contains("")); - EXPECT_TRUE(Filter.contains("aaaa")); - EXPECT_TRUE(Filter.contains("-*")); - EXPECT_TRUE(Filter.contains("-")); - EXPECT_TRUE(Filter.contains("*")); -} - -TEST(GlobList, Simple) { - GlobList Filter("aaa"); - - EXPECT_TRUE(Filter.contains("aaa")); - EXPECT_FALSE(Filter.contains("")); - EXPECT_FALSE(Filter.contains("aa")); - EXPECT_FALSE(Filter.contains("aaaa")); - EXPECT_FALSE(Filter.contains("bbb")); -} - -TEST(GlobList, WhitespacesAtBegin) { - GlobList Filter("-*, a.b.*"); - - EXPECT_TRUE(Filter.contains("a.b.c")); - EXPECT_FALSE(Filter.contains("b.c")); -} - -TEST(GlobList, Complex) { - GlobList Filter("*,-a.*, -b.*, \r \n a.1.* ,-a.1.A.*,-..,-...,-..+,-*$, -*qwe* "); - - EXPECT_TRUE(Filter.contains("aaa")); - EXPECT_TRUE(Filter.contains("qqq")); - EXPECT_FALSE(Filter.contains("a.")); - EXPECT_FALSE(Filter.contains("a.b")); - EXPECT_FALSE(Filter.contains("b.")); - EXPECT_FALSE(Filter.contains("b.b")); - EXPECT_TRUE(Filter.contains("a.1.b")); - EXPECT_FALSE(Filter.contains("a.1.A.a")); - EXPECT_FALSE(Filter.contains("qwe")); - EXPECT_FALSE(Filter.contains("asdfqweasdf")); - EXPECT_TRUE(Filter.contains("asdfqwEasdf")); -} - -} // namespace test -} // namespace tidy -} // namespace clang +#include "ClangTidy.h" +#include "ClangTidyTest.h" +#include "gtest/gtest.h" + +namespace clang { +namespace tidy { +namespace test { + +class TestCheck : public ClangTidyCheck { +public: + TestCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override { + Finder->addMatcher(ast_matchers::varDecl().bind("var"), this); + } + void check(const ast_matchers::MatchFinder::MatchResult &Result) override { + const auto *Var = Result.Nodes.getNodeAs("var"); + // Add diagnostics in the wrong order. + diag(Var->getLocation(), "variable"); + diag(Var->getTypeSpecStartLoc(), "type specifier"); + } +}; + +TEST(ClangTidyDiagnosticConsumer, SortsErrors) { + std::vector Errors; + runCheckOnCode("int a;", &Errors); + EXPECT_EQ(2ul, Errors.size()); + EXPECT_EQ("type specifier", Errors[0].Message.Message); + EXPECT_EQ("variable", Errors[1].Message.Message); +} + +TEST(GlobList, Empty) { + GlobList Filter(""); + + EXPECT_TRUE(Filter.contains("")); + EXPECT_FALSE(Filter.contains("aaa")); +} + +TEST(GlobList, Nothing) { + GlobList Filter("-*"); + + EXPECT_FALSE(Filter.contains("")); + EXPECT_FALSE(Filter.contains("a")); + EXPECT_FALSE(Filter.contains("-*")); + EXPECT_FALSE(Filter.contains("-")); + EXPECT_FALSE(Filter.contains("*")); +} + +TEST(GlobList, Everything) { + GlobList Filter("*"); + + EXPECT_TRUE(Filter.contains("")); + EXPECT_TRUE(Filter.contains("aaaa")); + EXPECT_TRUE(Filter.contains("-*")); + EXPECT_TRUE(Filter.contains("-")); + EXPECT_TRUE(Filter.contains("*")); +} + +TEST(GlobList, Simple) { + GlobList Filter("aaa"); + + EXPECT_TRUE(Filter.contains("aaa")); + EXPECT_FALSE(Filter.contains("")); + EXPECT_FALSE(Filter.contains("aa")); + EXPECT_FALSE(Filter.contains("aaaa")); + EXPECT_FALSE(Filter.contains("bbb")); +} + +TEST(GlobList, WhitespacesAtBegin) { + GlobList Filter("-*, a.b.*"); + + EXPECT_TRUE(Filter.contains("a.b.c")); + EXPECT_FALSE(Filter.contains("b.c")); +} + +TEST(GlobList, Complex) { + GlobList Filter("*,-a.*, -b.*, \r \n a.1.* ,-a.1.A.*,-..,-...,-..+,-*$, -*qwe* "); + + EXPECT_TRUE(Filter.contains("aaa")); + EXPECT_TRUE(Filter.contains("qqq")); + EXPECT_FALSE(Filter.contains("a.")); + EXPECT_FALSE(Filter.contains("a.b")); + EXPECT_FALSE(Filter.contains("b.")); + EXPECT_FALSE(Filter.contains("b.b")); + EXPECT_TRUE(Filter.contains("a.1.b")); + EXPECT_FALSE(Filter.contains("a.1.A.a")); + EXPECT_FALSE(Filter.contains("qwe")); + EXPECT_FALSE(Filter.contains("asdfqweasdf")); + EXPECT_TRUE(Filter.contains("asdfqwEasdf")); +} + +} // namespace test +} // namespace tidy +} // namespace clang diff --git a/clang/cmake/caches/Fuchsia-stage2.cmake b/clang/cmake/caches/Fuchsia-stage2.cmake index e93b6e4f07ad83..1f8a9e78763fa7 100644 --- a/clang/cmake/caches/Fuchsia-stage2.cmake +++ b/clang/cmake/caches/Fuchsia-stage2.cmake @@ -153,13 +153,21 @@ if(FUCHSIA_SDK) set(RUNTIMES_${target}-unknown-fuchsia+noexcept_LIBCXXABI_ENABLE_EXCEPTIONS OFF CACHE BOOL "") set(RUNTIMES_${target}-unknown-fuchsia+noexcept_LIBCXX_ENABLE_EXCEPTIONS OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia+asan+noexcept_LLVM_BUILD_COMPILER_RT OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia+asan+noexcept_LLVM_USE_SANITIZER "Address" CACHE STRING "") + set(RUNTIMES_${target}-unknown-fuchsia+asan+noexcept_LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia+asan+noexcept_LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia+asan+noexcept_LIBCXXABI_ENABLE_EXCEPTIONS OFF CACHE BOOL "") + set(RUNTIMES_${target}-unknown-fuchsia+asan+noexcept_LIBCXX_ENABLE_EXCEPTIONS OFF CACHE BOOL "") + # Use .build-id link. list(APPEND RUNTIME_BUILD_ID_LINK "${target}-unknown-fuchsia") endforeach() - set(LLVM_RUNTIME_MULTILIBS "asan;noexcept" CACHE STRING "") + set(LLVM_RUNTIME_MULTILIBS "asan;noexcept;asan+noexcept" CACHE STRING "") set(LLVM_RUNTIME_MULTILIB_asan_TARGETS "x86_64-unknown-fuchsia;aarch64-unknown-fuchsia" CACHE STRING "") set(LLVM_RUNTIME_MULTILIB_noexcept_TARGETS "x86_64-unknown-fuchsia;aarch64-unknown-fuchsia" CACHE STRING "") + set(LLVM_RUNTIME_MULTILIB_asan+noexcept_TARGETS "x86_64-unknown-fuchsia;aarch64-unknown-fuchsia" CACHE STRING "") endif() set(LLVM_BUILTIN_TARGETS "${BUILTIN_TARGETS}" CACHE STRING "") diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 61152a251bdba4..cb72c459c1e5b7 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1518,6 +1518,275 @@ parameters of protocol-qualified type. Query the presence of this new mangling with ``__has_feature(objc_protocol_qualifier_mangling)``. + +OpenCL Features +=============== + +C++ for OpenCL +-------------- + +This functionality is built on top of OpenCL C v2.0 and C++17. Regular C++ +features can be used in OpenCL kernel code. All functionality from OpenCL C +is inherited. This section describes minor differences to OpenCL C and any +limitations related to C++ support as well as interactions between OpenCL and +C++ features that are not documented elsewhere. + +Restrictions to C++17 +^^^^^^^^^^^^^^^^^^^^^ + +The following features are not supported: + +- Virtual functions +- ``dynamic_cast`` operator +- Non-placement ``new``/``delete`` operators +- Standard C++ libraries. Currently there is no solution for alternative C++ + libraries provided. Future release will feature library support. + + +Interplay of OpenCL and C++ features +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Address space behavior +"""""""""""""""""""""" + +Address spaces are part of the type qualifiers; many rules are just inherited +from the qualifier behavior documented in OpenCL C v2.0 s6.5 and Embedded C +extension ISO/IEC JTC1 SC22 WG14 N1021 s3.1. Note that since the address space +behavior in C++ is not documented formally yet, Clang extends existing concept +from C and OpenCL. For example conversion rules are extended from qualification +conversion but the compatibility is determined using sets and overlapping from +Embedded C (ISO/IEC JTC1 SC22 WG14 N1021 s3.1.3). For OpenCL it means that +implicit conversions are allowed from named to ``__generic`` but not vice versa +(OpenCL C v2.0 s6.5.5) except for ``__constant`` address space. Most of the +rules are built on top of this behavior. + +**Casts** + +C style cast will follow OpenCL C v2.0 rules (s6.5.5). All cast operators will +permit implicit conversion to ``__generic``. However converting from named +address spaces to ``__generic`` can only be done using ``addrspace_cast``. Note +that conversions between ``__constant`` and any other is still disallowed. + +.. _opencl_cpp_addrsp_deduction: + +**Deduction** + +Address spaces are not deduced for: + +- non-pointer/non-reference template parameters or any dependent types except + for template specializations. +- non-pointer/non-reference class members except for static data members that are + deduced to ``__global`` address space. +- non-pointer/non-reference alias declarations. +- ``decltype`` expression. + +.. code-block:: c++ + + template + void foo() { + T m; // address space of m will be known at template instantiation time. + T * ptr; // ptr points to __generic address space object. + T & ref = ...; // ref references an object in __generic address space. + }; + + template + struct S { + int i; // i has no address space + static int ii; // ii is in global address space + int * ptr; // ptr points to __generic address space int. + int & ref = ...; // ref references int in __generic address space. + }; + + template + void bar() + { + S s; // s is in __private address space + } + +TODO: Add example for type alias and decltype! + +**References** + +References types can be qualified with an address space. + +.. code-block:: c++ + + __private int & ref = ...; // references int in __private address space + +By default references will refer to ``__generic`` address space objects, except +for dependent types that are not template specializations +(see :ref:`Deduction `). Address space compatibility +checks are performed when references are bound to values. The logic follows the +rules from address space pointer conversion (OpenCL v2.0 s6.5.5). + +**Default address space** + +All non-static member functions take an implicit object parameter ``this`` that +is a pointer type. By default this pointer parameter is in ``__generic`` address +space. All concrete objects passed as an argument to ``this`` parameter will be +converted to ``__generic`` address space first if the conversion is valid. +Therefore programs using objects in ``__constant`` address space won't be compiled +unless address space is explicitly specified using address space qualifiers on +member functions +(see :ref:`Member function qualifier `) as the +conversion between ``__constant`` and ``__generic`` is disallowed. Member function +qualifiers can also be used in case conversion to ``__generic`` address space is +undesirable (even if it is legal), for example to take advantage of memory bank +accesses. Note this not only applies to regular member functions but to +constructors and destructors too. + +.. _opencl_cpp_addrspace_method_qual: + +**Member function qualifier** + +Clang allows specifying address space qualifier on member functions to signal that +they are to be used with objects constructed in some specific address space. This +works just the same as qualifying member functions with ``const`` or any other +qualifiers. The overloading resolution will select overload with most specific +address space if multiple candidates are provided. If there is no conversion to +to an address space among existing overloads compilation will fail with a +diagnostic. + +.. code-block:: c++ + + struct C { + void foo() __local; + void foo(); + }; + + __kernel void bar() { + __local C c1; + C c2; + __constant C c3; + c1.foo(); // will resolve to the first foo + c2.foo(); // will resolve to the second foo + c3.foo(); // error due to mismatching address spaces - can't convert to + // __local or __generic + } + +**Implicit special members** + +All implicit special members (default, copy, or move constructor, copy or move +assignment, destructor) will be generated with ``__generic`` address space. + +.. code-block:: c++ + + class C { + // Has the following implicit definition + // void C() __generic; + // void C(const __generic C &) __generic; + // void C(__generic C &&) __generic; + // operator= '__generic C &(__generic C &&)' + // operator= '__generic C &(const __generic C &) __generic + } + +**Builtin operators** + +All builtin operators are available in the specific address spaces, thus no conversion +to ``__generic`` is performed. + +**Templates** + +There is no deduction of address spaces in non-pointer/non-reference template parameters +and dependent types (see :ref:`Deduction `). The address +space of template parameter is deduced during the type deduction if it's not explicitly +provided in instantiation. + +.. code-block:: c++ + + 1 template + 2 void foo(T* i){ + 3 T var; + 4 } + 5 + 6 __global int g; + 7 void bar(){ + 8 foo(&g); // error: template instantiation failed as function scope variable appears to + 9 // be declared in __global address space (see line 3) + 10 } + +It is not legal to specify multiple different address spaces between template definition and +instantiation. If multiple different address spaces are specified in template definition and +instantiation compilation of such program will fail with a diagnostic. + +.. code-block:: c++ + + template + void foo() { + __private T var; + } + + void bar() { + foo<__global int>(); // error: conflicting address space qualifiers are provided __global + // and __private + } + +Once template is instantiated regular restrictions for address spaces will apply. + +.. code-block:: c++ + + template + void foo(){ + T var; + } + + void bar(){ + foo<__global int>(); // error: function scope variable cannot be declared in __global + // address space + } + +**Temporary materialization** + +All temporaries are materialized in ``__private`` address space. If a reference with some +other address space is bound to them, the conversion will be generated in case it's valid +otherwise compilation will fail with a diagnostic. + +.. code-block:: c++ + + int bar(const unsigned int &i); + + void foo() { + bar(1); // temporary is created in __private address space but converted + // to __generic address space of parameter reference + } + + __global const int& f(__global float &ref) { + return ref; // error: address space mismatch between temporary object + // created to hold value converted float->int and return + // value type (can't convert from __private to __global) + } + +**Initialization of local and constant address space objects** + +TODO + +Constructing and destroying global objects +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Global objects are constructed before the first kernel using the global +objects is executed and destroyed just after the last kernel using the +program objects is executed. In OpenCL v2.0 drivers there is no specific +API for invoking global constructors. However, an easy workaround would be +to enqueue constructor initialization kernel that has a name +``@_GLOBAL__sub_I_``. This kernel is only present if there +are any global objects to be initialized in the compiled binary. One way to +check this is by passing ``CL_PROGRAM_KERNEL_NAMES`` to ``clGetProgramInfo`` +(OpenCL v2.0 s5.8.7). + +Note that if multiple files are compiled and linked into libraries multiple +kernels that initialize global objects for multiple modules would have to be +invoked. + +.. code-block:: console + + clang -cl-std=c++ test.cl + +If there are any global objects to be initialized the final binary will +contain ``@_GLOBAL__sub_I_test.cl`` kernel to be enqueued. + +Global destructors can not be invoked in OpenCL v2.0 drivers. However, all +memory used for program scope objects is released on ``clReleaseProgram``. + Initializer lists for complex numbers in C ========================================== @@ -2467,6 +2736,10 @@ Which compiles to (on X86-32): movl %gs:(%eax), %eax ret +You can also use the GCC compatibility macros ``__seg_fs`` and ``__seg_gs`` for +the same purpose. The preprocessor symbols ``__SEG_FS`` and ``__SEG_GS`` +indicate their support. + PowerPC Language Extensions ------------------------------ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7185030a92d7c0..dadcc77f4803ec 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -56,10 +56,11 @@ Improvements to Clang's diagnostics Non-comprehensive list of changes in this release ------------------------------------------------- -- The ``__VERSION__`` macro has been removed. - Previously this macro was set to a string aiming to achieve compatibility with - GCC 4.2.1, but that should no longer be necessary. To get Clang's version, - use the :ref:`clang namespaced version macros `. +- The ``__VERSION__`` macro has been updated. + Previously this macro contained the string '4.2.1 Compatible' to achieve + compatibility with GCC 4.2.1, but that should no longer be necessary. + However, to retrieve Clang's version, please favor the one of the macro + defined in :ref:`clang namespaced version macros `. - ... @@ -84,11 +85,6 @@ Modified Compiler Flags - ... -Removed Compiler Options ------------------------- - -- ... - New Pragmas in Clang -------------------- @@ -194,8 +190,8 @@ AST Matchers clang-format ------------ -- Add language support for clang-formatting C# files -- Add Microsoft coding style to encapsulate default C# formatting style +- Add language support for clang-formatting C# files. +- Add Microsoft coding style to encapsulate default C# formatting style. - Added new option `PPDIS_BeforeHash` (in configuration: `BeforeHash`) to `IndentPPDirectives` which indents preprocessor directives before the hash. - Added new option `AlignConsecutiveMacros` to align the C/C++ preprocessor diff --git a/clang/docs/UndefinedBehaviorSanitizer.rst b/clang/docs/UndefinedBehaviorSanitizer.rst index 7a4eaf4f60d5d6..38cd3645bceacb 100644 --- a/clang/docs/UndefinedBehaviorSanitizer.rst +++ b/clang/docs/UndefinedBehaviorSanitizer.rst @@ -205,8 +205,8 @@ Minimal Runtime There is a minimal UBSan runtime available suitable for use in production environments. This runtime has a small attack surface. It only provides very -basic issue logging and deduplication, and does not support ``-fsanitize=vptr`` -checking. +basic issue logging and deduplication, and does not support +``-fsanitize=function`` and ``-fsanitize=vptr`` checking. To use the minimal runtime, add ``-fsanitize-minimal-runtime`` to the clang command line options. For example, if you're used to compiling with diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 001003a3fa6fcf..2fbb414f6820c6 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -2397,7 +2397,8 @@ Compiling to bitcode can be done as follows: This will produce a generic test.bc file that can be used in vendor toolchains to perform machine code generation. -Clang currently supports OpenCL C language standards up to v2.0. +Clang currently supports OpenCL C language standards up to v2.0. Starting from Clang9 +C++ mode is available for OpenCL (see :ref:`C++ for OpenCL `). OpenCL Specific Options ----------------------- @@ -2756,6 +2757,45 @@ There are some standard OpenCL functions that are implemented as Clang builtins: enqueue query functions from `section 6.13.17.5 `_. +.. _opencl_cpp: + +C++ for OpenCL +-------------- + +Starting from Clang9 kernel code can contain C++17 features: classes, templates, +function overloading, type deduction, etc. Please note that this is not an +implementation of `OpenCL C++ +`_ and +there is no plan to support it in clang in any new releases in the near future. + +There are only a few restrictions on allowed C++ features. For detailed information +please refer to documentation on Extensions (:doc:`LanguageExtensions`). + +Since C++ features are to be used on top of OpenCL C functionality, all existing +restrictions from OpenCL C v2.0 will inherently apply. All OpenCL C builtin types +and function libraries are supported and can be used in the new mode. + +To enable the new mode pass the following command line option when compiling ``.cl`` +file ``-cl-std=c++`` or ``-std=c++``. + + .. code-block:: c++ + + template T add( T x, T y ) + { + return x + y; + } + + __kernel void test( __global float* a, __global float* b) + { + auto index = get_global_id(0); + a[index] = add(b[index], b[index+1]); + } + + + .. code-block:: console + + clang -cl-std=c++ test.cl + .. _target_features: Target-Specific Features and Limitations diff --git a/clang/examples/clang-interpreter/main.cpp b/clang/examples/clang-interpreter/main.cpp index 8fb52700a757eb..69808428a34daf 100644 --- a/clang/examples/clang-interpreter/main.cpp +++ b/clang/examples/clang-interpreter/main.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" @@ -50,65 +51,69 @@ namespace orc { class SimpleJIT { private: ExecutionSession ES; - std::shared_ptr Resolver; std::unique_ptr TM; const DataLayout DL; - LegacyRTDyldObjectLinkingLayer ObjectLayer; - LegacyIRCompileLayer CompileLayer; + MangleAndInterner Mangle{ES, DL}; + RTDyldObjectLinkingLayer ObjectLayer{ES, createMemMgr}; + IRCompileLayer CompileLayer{ES, ObjectLayer, SimpleCompiler(*TM)}; -public: - SimpleJIT() - : Resolver(createLegacyLookupResolver( - ES, - [this](const std::string &Name) -> JITSymbol { - if (auto Sym = CompileLayer.findSymbol(Name, false)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - if (auto SymAddr = - RTDyldMemoryManager::getSymbolAddressInProcess(Name)) - return JITSymbol(SymAddr, JITSymbolFlags::Exported); - return nullptr; - }, - [](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })), - TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), - ObjectLayer(ES, - [this](VModuleKey) { - return LegacyRTDyldObjectLinkingLayer::Resources{ - std::make_shared(), Resolver}; - }), - CompileLayer(ObjectLayer, SimpleCompiler(*TM)) { + static std::unique_ptr createMemMgr() { + return llvm::make_unique(); + } + + SimpleJIT(std::unique_ptr TM, DataLayout DL, + DynamicLibrarySearchGenerator ProcessSymbolsGenerator) + : TM(std::move(TM)), DL(std::move(DL)) { llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); + ES.getMainJITDylib().setGenerator(std::move(ProcessSymbolsGenerator)); } - const TargetMachine &getTargetMachine() const { return *TM; } +public: + static Expected> Create() { + auto JTMB = JITTargetMachineBuilder::detectHost(); + if (!JTMB) + return JTMB.takeError(); + + auto TM = JTMB->createTargetMachine(); + if (!TM) + return TM.takeError(); + + auto DL = (*TM)->createDataLayout(); - VModuleKey addModule(std::unique_ptr M) { - // Add the module to the JIT with a new VModuleKey. - auto K = ES.allocateVModule(); - cantFail(CompileLayer.addModule(K, std::move(M))); - return K; + auto ProcessSymbolsGenerator = + DynamicLibrarySearchGenerator::GetForCurrentProcess( + DL.getGlobalPrefix()); + + if (!ProcessSymbolsGenerator) + return ProcessSymbolsGenerator.takeError(); + + return std::unique_ptr(new SimpleJIT( + std::move(*TM), std::move(DL), std::move(*ProcessSymbolsGenerator))); } - JITSymbol findSymbol(const StringRef &Name) { - std::string MangledName; - raw_string_ostream MangledNameStream(MangledName); - Mangler::getNameWithPrefix(MangledNameStream, Name, DL); - return CompileLayer.findSymbol(MangledNameStream.str(), true); + const TargetMachine &getTargetMachine() const { return *TM; } + + Error addModule(ThreadSafeModule M) { + return CompileLayer.add(ES.getMainJITDylib(), std::move(M)); } - JITTargetAddress getSymbolAddress(const StringRef &Name) { - return cantFail(findSymbol(Name).getAddress()); + Expected findSymbol(const StringRef &Name) { + return ES.lookup({&ES.getMainJITDylib()}, Mangle(Name)); } - void removeModule(VModuleKey K) { - cantFail(CompileLayer.removeModule(K)); + Expected getSymbolAddress(const StringRef &Name) { + auto Sym = findSymbol(Name); + if (!Sym) + return Sym.takeError(); + return Sym->getAddress(); } }; } // end namespace orc } // end namespace llvm +llvm::ExitOnError ExitOnErr; + int main(int argc, const char **argv) { // This just needs to be some symbol in the binary; C++ doesn't // allow taking the address of ::main however. @@ -130,6 +135,8 @@ int main(int argc, const char **argv) { T.setObjectFormat(llvm::Triple::ELF); #endif + ExitOnErr.setBanner("clang interpreter"); + Driver TheDriver(Path, T.str(), Diags); TheDriver.setTitle("clang interpreter"); TheDriver.setCheckInputsExist(false); @@ -204,14 +211,16 @@ int main(int argc, const char **argv) { llvm::InitializeNativeTargetAsmPrinter(); int Res = 255; + std::unique_ptr Ctx(Act->takeLLVMContext()); std::unique_ptr Module = Act->takeModule(); if (Module) { - llvm::orc::SimpleJIT J; - auto H = J.addModule(std::move(Module)); - auto Main = (int(*)(...))J.getSymbolAddress("main"); + auto J = ExitOnErr(llvm::orc::SimpleJIT::Create()); + + ExitOnErr(J->addModule( + llvm::orc::ThreadSafeModule(std::move(Module), std::move(Ctx)))); + auto Main = (int (*)(...))ExitOnErr(J->getSymbolAddress("main")); Res = Main(); - J.removeModule(H); } // Shutdown. diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index e593dafb5fc4da..02742801f37c20 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -3746,6 +3746,30 @@ class RecordDecl : public TagDecl { RecordDeclBits.NonTrivialToPrimitiveDestroy = V; } + bool hasNonTrivialToPrimitiveDefaultInitializeCUnion() const { + return RecordDeclBits.HasNonTrivialToPrimitiveDefaultInitializeCUnion; + } + + void setHasNonTrivialToPrimitiveDefaultInitializeCUnion(bool V) { + RecordDeclBits.HasNonTrivialToPrimitiveDefaultInitializeCUnion = V; + } + + bool hasNonTrivialToPrimitiveDestructCUnion() const { + return RecordDeclBits.HasNonTrivialToPrimitiveDestructCUnion; + } + + void setHasNonTrivialToPrimitiveDestructCUnion(bool V) { + RecordDeclBits.HasNonTrivialToPrimitiveDestructCUnion = V; + } + + bool hasNonTrivialToPrimitiveCopyCUnion() const { + return RecordDeclBits.HasNonTrivialToPrimitiveCopyCUnion; + } + + void setHasNonTrivialToPrimitiveCopyCUnion(bool V) { + RecordDeclBits.HasNonTrivialToPrimitiveCopyCUnion = V; + } + /// Determine whether this class can be passed in registers. In C++ mode, /// it must have at least one trivial, non-deleted copy or move constructor. /// FIXME: This should be set as part of completeDefinition. diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 26edb7790c2617..d64d0cb425db0a 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -1440,6 +1440,13 @@ class DeclContext { uint64_t NonTrivialToPrimitiveCopy : 1; uint64_t NonTrivialToPrimitiveDestroy : 1; + /// The following bits indicate whether this is or contains a C union that + /// is non-trivial to default-initialize, destruct, or copy. These bits + /// imply the associated basic non-triviality predicates declared above. + uint64_t HasNonTrivialToPrimitiveDefaultInitializeCUnion : 1; + uint64_t HasNonTrivialToPrimitiveDestructCUnion : 1; + uint64_t HasNonTrivialToPrimitiveCopyCUnion : 1; + /// Indicates whether this struct is destroyed in the callee. uint64_t ParamDestroyedInCallee : 1; @@ -1448,7 +1455,7 @@ class DeclContext { }; /// Number of non-inherited bits in RecordDeclBitfields. - enum { NumRecordDeclBits = 11 }; + enum { NumRecordDeclBits = 14 }; /// Stores the bits used by OMPDeclareReductionDecl. /// If modified NumOMPDeclareReductionDeclBits and the accessor diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index c6daf73a623bd0..eadcc62a34575d 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -501,11 +501,10 @@ class OMPIfClause : public OMPClause, public OMPClauseWithPreInit { return const_child_range(&Condition, &Condition + 1); } - child_range used_children() { - return child_range(child_iterator(), child_iterator()); - } + child_range used_children(); const_child_range used_children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); + auto Children = const_cast(this)->used_children(); + return const_child_range(Children.begin(), Children.end()); } static bool classof(const OMPClause *T) { diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 00a2b7643370a4..584655fe789e63 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -1129,12 +1129,6 @@ class QualType { PCK_Struct }; - /// Check if this is a non-trivial type that would cause a C struct - /// transitively containing this type to be non-trivial. This function can be - /// used to determine whether a field of this type can be declared inside a C - /// union. - bool isNonTrivialPrimitiveCType(const ASTContext &Ctx) const; - /// Check if this is a non-trivial type that would cause a C struct /// transitively containing this type to be non-trivial to copy and return the /// kind. @@ -1164,6 +1158,22 @@ class QualType { return isDestructedTypeImpl(*this); } + /// Check if this is or contains a C union that is non-trivial to + /// default-initialize, which is a union that has a member that is non-trivial + /// to default-initialize. If this returns true, + /// isNonTrivialToPrimitiveDefaultInitialize returns PDIK_Struct. + bool hasNonTrivialToPrimitiveDefaultInitializeCUnion() const; + + /// Check if this is or contains a C union that is non-trivial to destruct, + /// which is a union that has a member that is non-trivial to destruct. If + /// this returns true, isDestructedType returns DK_nontrivial_c_struct. + bool hasNonTrivialToPrimitiveDestructCUnion() const; + + /// Check if this is or contains a C union that is non-trivial to copy, which + /// is a union that has a member that is non-trivial to copy. If this returns + /// true, isNonTrivialToPrimitiveCopy returns PCK_Struct. + bool hasNonTrivialToPrimitiveCopyCUnion() const; + /// Determine whether expressions of the given type are forbidden /// from being lvalues in C. /// @@ -1236,6 +1246,11 @@ class QualType { const ASTContext &C); static QualType IgnoreParens(QualType T); static DestructionKind isDestructedTypeImpl(QualType type); + + /// Check if \param RD is or contains a non-trivial C union. + static bool hasNonTrivialToPrimitiveDefaultInitializeCUnion(const RecordDecl *RD); + static bool hasNonTrivialToPrimitiveDestructCUnion(const RecordDecl *RD); + static bool hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD); }; } // namespace clang @@ -6249,6 +6264,24 @@ inline Qualifiers::GC QualType::getObjCGCAttr() const { return getQualifiers().getObjCGCAttr(); } +inline bool QualType::hasNonTrivialToPrimitiveDefaultInitializeCUnion() const { + if (auto *RD = getTypePtr()->getBaseElementTypeUnsafe()->getAsRecordDecl()) + return hasNonTrivialToPrimitiveDefaultInitializeCUnion(RD); + return false; +} + +inline bool QualType::hasNonTrivialToPrimitiveDestructCUnion() const { + if (auto *RD = getTypePtr()->getBaseElementTypeUnsafe()->getAsRecordDecl()) + return hasNonTrivialToPrimitiveDestructCUnion(RD); + return false; +} + +inline bool QualType::hasNonTrivialToPrimitiveCopyCUnion() const { + if (auto *RD = getTypePtr()->getBaseElementTypeUnsafe()->getAsRecordDecl()) + return hasNonTrivialToPrimitiveCopyCUnion(RD); + return false; +} + inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) { if (const auto *PT = t.getAs()) { if (const auto *FT = PT->getPointeeType()->getAs()) diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def index 5ba03da4a7a05f..7701ad98f4832c 100644 --- a/clang/include/clang/Basic/BuiltinsAArch64.def +++ b/clang/include/clang/Basic/BuiltinsAArch64.def @@ -65,6 +65,8 @@ BUILTIN(__builtin_arm_dmb, "vUi", "nc") BUILTIN(__builtin_arm_dsb, "vUi", "nc") BUILTIN(__builtin_arm_isb, "vUi", "nc") +BUILTIN(__builtin_arm_jcvt, "Zid", "nc") + // Prefetch BUILTIN(__builtin_arm_prefetch, "vvC*UiUiUiUi", "nc") diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def index e882d3b87c6664..2f8fb9000a76a9 100644 --- a/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -108,6 +108,16 @@ BUILTIN(__builtin_amdgcn_ds_fminf, "ff*3fIiIiIb", "n") BUILTIN(__builtin_amdgcn_ds_fmaxf, "ff*3fIiIiIb", "n") BUILTIN(__builtin_amdgcn_ds_append, "ii*3", "n") BUILTIN(__builtin_amdgcn_ds_consume, "ii*3", "n") +BUILTIN(__builtin_amdgcn_alignbit, "UiUiUiUi", "nc") +BUILTIN(__builtin_amdgcn_alignbyte, "UiUiUiUi", "nc") +BUILTIN(__builtin_amdgcn_ubfe, "UiUiUiUi", "nc") +BUILTIN(__builtin_amdgcn_sbfe, "UiUiUiUi", "nc") +BUILTIN(__builtin_amdgcn_cvt_pkrtz, "E2hff", "nc") +BUILTIN(__builtin_amdgcn_cvt_pknorm_i16, "E2sff", "nc") +BUILTIN(__builtin_amdgcn_cvt_pknorm_u16, "E2Usff", "nc") +BUILTIN(__builtin_amdgcn_cvt_pk_i16, "E2sii", "nc") +BUILTIN(__builtin_amdgcn_cvt_pk_u16, "E2UsUiUi", "nc") +BUILTIN(__builtin_amdgcn_cvt_pk_u8_f32, "UifUiUi", "nc") //===----------------------------------------------------------------------===// // CI+ only builtins. @@ -162,6 +172,13 @@ TARGET_BUILTIN(__builtin_amdgcn_udot4, "UiUiUiUiIb", "nc", "dot2-insts") TARGET_BUILTIN(__builtin_amdgcn_sdot8, "SiSiSiSiIb", "nc", "dot1-insts") TARGET_BUILTIN(__builtin_amdgcn_udot8, "UiUiUiUiIb", "nc", "dot2-insts") +//===----------------------------------------------------------------------===// +// GFX10+ only builtins. +//===----------------------------------------------------------------------===// +TARGET_BUILTIN(__builtin_amdgcn_permlane16, "UiUiUiUiUiIbIb", "nc", "gfx10-insts") +TARGET_BUILTIN(__builtin_amdgcn_permlanex16, "UiUiUiUiUiIbIb", "nc", "gfx10-insts") +TARGET_BUILTIN(__builtin_amdgcn_mov_dpp8, "UiUiIUi", "nc", "gfx10-insts") + //===----------------------------------------------------------------------===// // Special builtins. //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/Basic/BuiltinsWebAssembly.def b/clang/include/clang/Basic/BuiltinsWebAssembly.def index 57ebb27ab4695c..63177f016ac770 100644 --- a/clang/include/clang/Basic/BuiltinsWebAssembly.def +++ b/clang/include/clang/Basic/BuiltinsWebAssembly.def @@ -29,6 +29,9 @@ BUILTIN(__builtin_wasm_memory_grow, "zIiz", "n") TARGET_BUILTIN(__builtin_wasm_memory_init, "vIUiIUiv*UiUi", "", "bulk-memory") TARGET_BUILTIN(__builtin_wasm_data_drop, "vIUi", "", "bulk-memory") +// Thread-local storage +TARGET_BUILTIN(__builtin_wasm_tls_size, "z", "nc", "bulk-memory") + // Floating point min/max BUILTIN(__builtin_wasm_min_f32, "fff", "nc") BUILTIN(__builtin_wasm_max_f32, "fff", "nc") diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index 776d16bd544b6b..ca2faf59d70f97 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -132,8 +132,8 @@ def err_nullability_conflicting : Error< // OpenCL Section 6.8.g def err_opencl_unknown_type_specifier : Error< - "OpenCL %select{C|C++}0 version %1 does not support the '%2' " - "%select{type qualifier|storage class specifier}3">; + "%select{OpenCL C|C++ for OpenCL}0 version %1 does not support the " + "'%2' %select{type qualifier|storage class specifier}3">; def warn_unknown_attribute_ignored : Warning< "unknown attribute %0 ignored">, InGroup; @@ -291,9 +291,9 @@ def note_mt_message : Note<"[rewriter] %0">; def warn_arcmt_nsalloc_realloc : Warning<"[rewriter] call returns pointer to GC managed memory; it will become unmanaged in ARC">; def err_arcmt_nsinvocation_ownership : Error<"NSInvocation's %0 is not safe to be used with an object with ownership other than __unsafe_unretained">; -// OpenCL C++. +// C++ for OpenCL. def err_openclcxx_not_supported : Error< - "'%0' is not supported in OpenCL C++">; + "'%0' is not supported in C++ for OpenCL">; // OpenMP def err_omp_more_one_clause : Error< diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index dd86ca49b7a288..eab453ee20ec9f 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -159,6 +159,8 @@ def err_drv_cannot_read_config_file : Error< "cannot read configuration file '%0'">; def err_drv_nested_config_file: Error< "option '--config' is not allowed inside configuration file">; +def err_drv_arg_requires_bitcode_input: Error< + "option '%0' requires input to be LLVM bitcode">; def err_target_unsupported_arch : Error<"the target architecture '%0' is not supported by the target '%1'">; diff --git a/clang/include/clang/Basic/DiagnosticIDs.h b/clang/include/clang/Basic/DiagnosticIDs.h index fccd534be350f4..5b9391b5a45275 100644 --- a/clang/include/clang/Basic/DiagnosticIDs.h +++ b/clang/include/clang/Basic/DiagnosticIDs.h @@ -169,7 +169,7 @@ class DiagnosticIDs : public RefCountedBase { private: /// Information for uniquing and looking up custom diags. - diag::CustomDiagInfo *CustomDiagInfo; + std::unique_ptr CustomDiagInfo; public: DiagnosticIDs(); diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 608337ed316e84..8e6ced0dea54fe 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1154,9 +1154,9 @@ def err_opencl_taking_function_address_parser : Error< def err_opencl_logical_exclusive_or : Error< "^^ is a reserved operator in OpenCL">; -// OpenCL C++. +// C++ for OpenCL. def err_openclcxx_virtual_function : Error< - "virtual functions are not supported in OpenCL C++">; + "virtual functions are not supported in C++ for OpenCL">; // OpenMP support. def warn_pragma_omp_ignored : Warning< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 380db32ba4bf50..effcbad78b2318 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -620,8 +620,23 @@ def warn_cstruct_memaccess : Warning< InGroup; def note_nontrivial_field : Note< "field is non-trivial to %select{copy|default-initialize}0">; -def err_nontrivial_primitive_type_in_union : Error< - "non-trivial C types are disallowed in union">; +def err_non_trivial_c_union_in_invalid_context : Error< + "cannot %select{" + "use type %1 for a function/method parameter|" + "use type %1 for function/method return|" + "default-initialize an object of type %1|" + "declare an automatic variable of type %1|" + "copy-initialize an object of type %1|" + "assign to a variable of type %1|" + "construct an automatic compound literal of type %1|" + "capture a variable of type %1|" + "cannot use volatile type %1 where it causes an lvalue-to-rvalue conversion" + "}3 " + "since it %select{contains|is}2 a union that is non-trivial to " + "%select{default-initialize|destruct|copy}0">; +def note_non_trivial_c_union : Note< + "%select{%2 has subobjects that are|%3 has type %2 that is}0 " + "non-trivial to %select{default-initialize|destruct|copy}1">; def warn_dyn_class_memaccess : Warning< "%select{destination for|source of|first operand of|second operand of}0 this " "%1 call is a pointer to %select{|class containing a }2dynamic class %3; " @@ -2942,8 +2957,8 @@ def err_attribute_vecreturn_only_pod_record : Error< def err_cconv_change : Error< "function declared '%0' here was previously declared " "%select{'%2'|without calling convention}1">; -def warn_cconv_ignored : Warning< - "%0 calling convention ignored %select{" +def warn_cconv_unsupported : Warning< + "%0 calling convention is not supported %select{" // Use CallingConventionIgnoredReason Enum to specify these. "for this target" "|on variadic function" diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index 7ab7c4d17005b6..7081c02e83eac9 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -42,6 +42,7 @@ FEATURE(address_sanitizer, FEATURE(hwaddress_sanitizer, LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress)) +FEATURE(memtag_sanitizer, LangOpts.Sanitize.has(SanitizerKind::MemTag)) FEATURE(xray_instrument, LangOpts.XRayInstrument) FEATURE(undefined_behavior_sanitizer, LangOpts.Sanitize.hasOneOf(SanitizerKind::Undefined)) diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 46012f73aa8b84..31aca2b0d69508 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -172,6 +172,7 @@ VALUE_LANGOPT(MaxTypeAlign , 32, 0, "default maximum alignment for types") VALUE_LANGOPT(AlignDouble , 1, 0, "Controls if doubles should be aligned to 8 bytes (x86 only)") VALUE_LANGOPT(LongDoubleSize , 32, 0, "width of long double") +LANGOPT(PPCIEEELongDouble , 1, 0, "use IEEE 754 quadruple-precision for long double") COMPATIBLE_VALUE_LANGOPT(PICLevel , 2, 0, "__PIC__ level") COMPATIBLE_VALUE_LANGOPT(PIE , 1, 0, "is pie") LANGOPT(ROPI , 1, 0, "Read-only position independence") @@ -196,8 +197,8 @@ LANGOPT(ShortEnums , 1, 0, "short enum types") LANGOPT(OpenCL , 1, 0, "OpenCL") LANGOPT(OpenCLVersion , 32, 0, "OpenCL C version") -LANGOPT(OpenCLCPlusPlus , 1, 0, "OpenCL C++") -LANGOPT(OpenCLCPlusPlusVersion , 32, 0, "OpenCL C++ version") +LANGOPT(OpenCLCPlusPlus , 1, 0, "C++ for OpenCL") +LANGOPT(OpenCLCPlusPlusVersion , 32, 0, "C++ for OpenCL version") LANGOPT(NativeHalfType , 1, 0, "Native half type support") LANGOPT(NativeHalfArgsAndReturns, 1, 0, "Native half args and returns") LANGOPT(HalfArgsAndReturns, 1, 0, "half args and returns") diff --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def index 1bb433a2b0e9b4..0037cc2146f26e 100644 --- a/clang/include/clang/Basic/Sanitizers.def +++ b/clang/include/clang/Basic/Sanitizers.def @@ -55,6 +55,9 @@ SANITIZER("hwaddress", HWAddress) // Kernel Hardware-assisted AddressSanitizer (KHWASan) SANITIZER("kernel-hwaddress", KernelHWAddress) +// A variant of AddressSanitizer using AArch64 MTE extension. +SANITIZER("memtag", MemTag) + // MemorySanitizer SANITIZER("memory", Memory) diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index 388fc1c1f86222..e32f749ae6abdf 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -679,7 +679,7 @@ class SourceManager : public RefCountedBase { /// Holds information for \#line directives. /// /// This is referenced by indices from SLocEntryTable. - LineTableInfo *LineTable = nullptr; + std::unique_ptr LineTable; /// These ivars serve as a cache used in the getLineNumber /// method which is used to speedup getLineNumber calls to nearby locations. diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 764f586f1439b1..55e94d387c9d47 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -252,9 +252,8 @@ PUNCTUATOR(caretcaret, "^^") // KEYNOMS18 - This is a keyword that must never be enabled under // MSVC <= v18. // KEYOPENCLC - This is a keyword in OpenCL C -// KEYOPENCLCXX - This is a keyword in OpenCL C++ -// KEYNOOPENCL - This is a keyword that is not supported in OpenCL C -// nor in OpenCL C++. +// KEYOPENCLCXX - This is a keyword in C++ for OpenCL +// KEYNOOPENCL - This is a keyword that is not supported in OpenCL // KEYALTIVEC - This is a keyword in AltiVec // KEYZVECTOR - This is a keyword for the System z vector extensions, // which are heavily based on AltiVec diff --git a/clang/include/clang/DirectoryWatcher/DirectoryWatcher.h b/clang/include/clang/DirectoryWatcher/DirectoryWatcher.h index 0bf966bb832ab9..e74443e0bc81c8 100644 --- a/clang/include/clang/DirectoryWatcher/DirectoryWatcher.h +++ b/clang/include/clang/DirectoryWatcher/DirectoryWatcher.h @@ -98,8 +98,7 @@ class DirectoryWatcher { : Kind(Kind), Filename(Filename) {} }; - /// Returns nullptr if \param Path doesn't exist. - /// Returns nullptr if \param Path isn't a directory. + /// Returns nullptr if \param Path doesn't exist or isn't a directory. /// Returns nullptr if OS kernel API told us we can't start watching. In such /// case it's unclear whether just retrying has any chance to succeeed. static std::unique_ptr diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 8862a015827bda..1f6c000ecf6a11 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -298,6 +298,8 @@ def menable_unsafe_fp_math : Flag<["-"], "menable-unsafe-fp-math">, "precision">; def mreassociate : Flag<["-"], "mreassociate">, HelpText<"Allow reassociation transformations for floating-point instructions">; +def mabi_EQ_ieeelongdouble : Flag<["-"], "mabi=ieeelongdouble">, + HelpText<"Use IEEE 754 quadruple-precision for long double">; def mfloat_abi : Separate<["-"], "mfloat-abi">, HelpText<"The float ABI to use">; def mtp : Separate<["-"], "mtp">, diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 957483c3186473..dfd27fab796e3a 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1270,7 +1270,7 @@ def flto_jobs_EQ : Joined<["-"], "flto-jobs=">, "of 0 means the number of threads will be derived from " "the number of CPUs detected)">; def fthinlto_index_EQ : Joined<["-"], "fthinlto-index=">, - Flags<[CC1Option]>, Group, + Flags<[CoreOption, CC1Option]>, Group, HelpText<"Perform ThinLTO importing using provided function summary index">; def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">, Group, Flags<[DriverOption, CoreOption]>; diff --git a/clang/include/clang/Frontend/LangStandards.def b/clang/include/clang/Frontend/LangStandards.def index 44a080d6d12fcf..0964e9b90a0383 100644 --- a/clang/include/clang/Frontend/LangStandards.def +++ b/clang/include/clang/Frontend/LangStandards.def @@ -166,7 +166,7 @@ LANGSTANDARD(opencl20, "cl2.0", OpenCL, "OpenCL 2.0", LineComment | C99 | Digraphs | HexFloat | OpenCL) LANGSTANDARD(openclcpp, "c++", - OpenCL, "OpenCL C++ 1.0", + OpenCL, "C++ for OpenCL", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | Digraphs | HexFloat | OpenCL) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 8f66cda46b65ca..af762f74d745c9 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2114,6 +2114,48 @@ class Sema { bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg, SourceLocation EqualLoc); + // Contexts where using non-trivial C union types can be disallowed. This is + // passed to err_non_trivial_c_union_in_invalid_context. + enum NonTrivialCUnionContext { + // Function parameter. + NTCUC_FunctionParam, + // Function return. + NTCUC_FunctionReturn, + // Default-initialized object. + NTCUC_DefaultInitializedObject, + // Variable with automatic storage duration. + NTCUC_AutoVar, + // Initializer expression that might copy from another object. + NTCUC_CopyInit, + // Assignment. + NTCUC_Assignment, + // Compound literal. + NTCUC_CompoundLiteral, + // Block capture. + NTCUC_BlockCapture, + // lvalue-to-rvalue conversion of volatile type. + NTCUC_LValueToRValueVolatile, + }; + + /// Emit diagnostics if the initializer or any of its explicit or + /// implicitly-generated subexpressions require copying or + /// default-initializing a type that is or contains a C union type that is + /// non-trivial to copy or default-initialize. + void checkNonTrivialCUnionInInitializer(const Expr *Init, SourceLocation Loc); + + // These flags are passed to checkNonTrivialCUnion. + enum NonTrivialCUnionKind { + NTCUK_Init = 0x1, + NTCUK_Destruct = 0x2, + NTCUK_Copy = 0x4, + }; + + /// Emit diagnostics if a non-trivial C union type or a struct that contains + /// a non-trivial C union is used in an invalid context. + void checkNonTrivialCUnion(QualType QT, SourceLocation Loc, + NonTrivialCUnionContext UseContext, + unsigned NonTrivialKind); + void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit); void ActOnUninitializedDecl(Decl *dcl); void ActOnInitializerError(Decl *Dcl); diff --git a/clang/lib/ARCMigrate/ARCMT.cpp b/clang/lib/ARCMigrate/ARCMT.cpp index 6a5efc00d7e857..568e06f21fba6a 100644 --- a/clang/lib/ARCMigrate/ARCMT.cpp +++ b/clang/lib/ARCMigrate/ARCMT.cpp @@ -514,7 +514,7 @@ MigrationProcess::MigrationProcess( IntrusiveRefCntPtr Diags( new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient, /*ShouldOwnClient=*/false)); - Remapper.initFromDisk(outputDir, *Diags, /*ignoreIfFilesChanges=*/true); + Remapper.initFromDisk(outputDir, *Diags, /*ignoreIfFilesChanged=*/true); } } diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp index f22e03f490f47f..7126a0873ea0c6 100644 --- a/clang/lib/ARCMigrate/ObjCMT.cpp +++ b/clang/lib/ARCMigrate/ObjCMT.cpp @@ -110,7 +110,7 @@ class ObjCMigrateASTConsumer : public ASTConsumer { if (!Summaries) Summaries.reset(new RetainSummaryManager(Ctx, /*TrackNSCFObjects=*/true, - /*TrackOSObjects=*/false)); + /*trackOSObjects=*/false)); return *Summaries; } @@ -216,7 +216,7 @@ ObjCMigrateAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { bool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) { Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(), - /*ignoreIfFilesChanges=*/true); + /*ignoreIfFilesChanged=*/true); CompInst = &CI; CI.getDiagnostics().setIgnoreAllWarnings(true); return true; diff --git a/clang/lib/ARCMigrate/TransGCAttrs.cpp b/clang/lib/ARCMigrate/TransGCAttrs.cpp index fdbe1d119af816..5e3162197ed1b0 100644 --- a/clang/lib/ARCMigrate/TransGCAttrs.cpp +++ b/clang/lib/ARCMigrate/TransGCAttrs.cpp @@ -269,7 +269,7 @@ static void checkAllAtProps(MigrationContext &MigrateCtx, StringRef toAttr = "strong"; if (hasWeak) { if (canApplyWeak(MigrateCtx.Pass.Ctx, IndProps.front()->getType(), - /*AllowOnUnkwownClass=*/true)) + /*AllowOnUnknownClass=*/true)) toAttr = "weak"; else toAttr = "unsafe_unretained"; diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 863a1cb0af8c17..9d5dd84161dec4 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1707,6 +1707,17 @@ static Error setTypedefNameForAnonDecl(TagDecl *From, TagDecl *To, Error ASTNodeImporter::ImportDefinition( RecordDecl *From, RecordDecl *To, ImportDefinitionKind Kind) { + auto DefinitionCompleter = [To]() { + // There are cases in LLDB when we first import a class without its + // members. The class will have DefinitionData, but no members. Then, + // importDefinition is called from LLDB, which tries to get the members, so + // when we get here, the class already has the DefinitionData set, so we + // must unset the CompleteDefinition here to be able to complete again the + // definition. + To->setCompleteDefinition(false); + To->completeDefinition(); + }; + if (To->getDefinition() || To->isBeingDefined()) { if (Kind == IDK_Everything || // In case of lambdas, the class already has a definition ptr set, but @@ -1717,7 +1728,7 @@ Error ASTNodeImporter::ImportDefinition( Error Result = ImportDeclContext(From, /*ForceImport=*/true); // Finish the definition of the lambda, set isBeingDefined to false. if (To->isLambda()) - To->completeDefinition(); + DefinitionCompleter(); return Result; } @@ -1728,8 +1739,8 @@ Error ASTNodeImporter::ImportDefinition( // Complete the definition even if error is returned. // The RecordDecl may be already part of the AST so it is better to // have it in complete state even if something is wrong with it. - auto DefinitionCompleter = - llvm::make_scope_exit([To]() { To->completeDefinition(); }); + auto DefinitionCompleterScopeExit = + llvm::make_scope_exit(DefinitionCompleter); if (Error Err = setTypedefNameForAnonDecl(From, To, Importer)) return Err; @@ -7757,10 +7768,20 @@ ASTImporter::findDeclsInToCtx(DeclContext *DC, DeclarationName Name) { SharedState->getLookupTable()->lookup(ReDC, Name); return FoundDeclsTy(LookupResult.begin(), LookupResult.end()); } else { - // FIXME Can we remove this kind of lookup? - // Or lldb really needs this C/C++ lookup? - FoundDeclsTy Result; - ReDC->localUncachedLookup(Name, Result); + DeclContext::lookup_result NoloadLookupResult = ReDC->noload_lookup(Name); + FoundDeclsTy Result(NoloadLookupResult.begin(), NoloadLookupResult.end()); + // We must search by the slow case of localUncachedLookup because that is + // working even if there is no LookupPtr for the DC. We could use + // DC::buildLookup() to create the LookupPtr, but that would load external + // decls again, we must avoid that case. + // Also, even if we had the LookupPtr, we must find Decls which are not + // in the LookupPtr, so we need the slow case. + // These cases are handled in ASTImporterLookupTable, but we cannot use + // that with LLDB since that traverses through the AST which initiates the + // load of external decls again via DC::decls(). And again, we must avoid + // loading external decls during the import. + if (Result.empty()) + ReDC->localUncachedLookup(Name, Result); return Result; } } @@ -8075,7 +8096,7 @@ ASTImporter::Import(NestedNameSpecifier *FromNNS) { if (!FromNNS) return nullptr; - NestedNameSpecifier *Prefix; + NestedNameSpecifier *Prefix = nullptr; if (Error Err = importInto(Prefix, FromNNS->getPrefix())) return std::move(Err); diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index bb2e353eeef2b0..912db3c130c51b 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -1085,6 +1085,19 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return true; } +/// Determine structural equivalence of two lambda classes. +static bool +IsStructurallyEquivalentLambdas(StructuralEquivalenceContext &Context, + CXXRecordDecl *D1, CXXRecordDecl *D2) { + assert(D1->isLambda() && D2->isLambda() && + "Must be called on lambda classes"); + if (!IsStructurallyEquivalent(Context, D1->getLambdaCallOperator(), + D2->getLambdaCallOperator())) + return false; + + return true; +} + /// Determine structural equivalence of two records. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, RecordDecl *D1, RecordDecl *D2) { @@ -1166,6 +1179,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, D1CXX->getASTContext().getExternalSource()->CompleteType(D1CXX); } + if (D1CXX->isLambda() != D2CXX->isLambda()) + return false; + if (D1CXX->isLambda()) { + if (!IsStructurallyEquivalentLambdas(Context, D1CXX, D2CXX)) + return false; + } + if (D1CXX->getNumBases() != D2CXX->getNumBases()) { if (Context.Complain) { Context.Diag2(D2->getLocation(), diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 21dd5425834a93..21cf9da18a8b23 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4252,6 +4252,9 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C, setNonTrivialToPrimitiveDefaultInitialize(false); setNonTrivialToPrimitiveCopy(false); setNonTrivialToPrimitiveDestroy(false); + setHasNonTrivialToPrimitiveDefaultInitializeCUnion(false); + setHasNonTrivialToPrimitiveDestructCUnion(false); + setHasNonTrivialToPrimitiveCopyCUnion(false); setParamDestroyedInCallee(false); setArgPassingRestrictions(APK_CanPassInRegs); } diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index f8017bb7adebee..6ef77b8aee6848 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -2201,7 +2201,7 @@ APValue SourceLocExpr::EvaluateInContext(const ASTContext &Ctx, case SourceLocExpr::Line: case SourceLocExpr::Column: { llvm::APSInt IntVal(Ctx.getIntWidth(Ctx.UnsignedIntTy), - /*IsUnsigned=*/true); + /*isUnsigned=*/true); IntVal = getIdentKind() == SourceLocExpr::Line ? PLoc.getLine() : PLoc.getColumn(); return APValue(IntVal); @@ -2303,11 +2303,11 @@ bool InitListExpr::isTransparent() const { bool InitListExpr::isIdiomaticZeroInitializer(const LangOptions &LangOpts) const { assert(isSyntacticForm() && "only test syntactic form as zero initializer"); - if (LangOpts.CPlusPlus || getNumInits() != 1) { + if (LangOpts.CPlusPlus || getNumInits() != 1 || !getInit(0)) { return false; } - const IntegerLiteral *Lit = dyn_cast(getInit(0)); + const IntegerLiteral *Lit = dyn_cast(getInit(0)->IgnoreImplicit()); return Lit && Lit->getValue() == 0; } diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 5f4644b0f7c319..6c813f09a4b3cc 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -3787,7 +3787,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { if (TypeSourceInfo *ScopeInfo = PDE->getScopeTypeInfo()) { if (Qualifier) { mangleUnresolvedPrefix(Qualifier, - /*Recursive=*/true); + /*recursive=*/true); mangleUnresolvedTypeOrSimpleId(ScopeInfo->getType()); Out << 'E'; } else { diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp index 5582dc582aca20..625282368a4d1b 100644 --- a/clang/lib/AST/Mangle.cpp +++ b/clang/lib/AST/Mangle.cpp @@ -379,7 +379,7 @@ class ASTNameGenerator::Implementation { auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) { auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false, - /*IsCSSMethod=*/true); + /*IsCXXMethod=*/true); auto CC = MD->getType()->getAs()->getCallConv(); return CC == DefaultCC; }; diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp index 41520b380276c6..9d8a7ebc3023ed 100644 --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -209,6 +209,25 @@ const OMPClauseWithPostUpdate *OMPClauseWithPostUpdate::get(const OMPClause *C) return nullptr; } +/// Gets the address of the original, non-captured, expression used in the +/// clause as the preinitializer. +static Stmt **getAddrOfExprAsWritten(Stmt *S) { + if (!S) + return nullptr; + if (auto *DS = dyn_cast(S)) { + assert(DS->isSingleDecl() && "Only single expression must be captured."); + if (auto *OED = dyn_cast(DS->getSingleDecl())) + return OED->getInitAddress(); + } + return nullptr; +} + +OMPClause::child_range OMPIfClause::used_children() { + if (Stmt **C = getAddrOfExprAsWritten(getPreInitStmt())) + return child_range(C, C + 1); + return child_range(&Condition, &Condition + 1); +} + OMPOrderedClause *OMPOrderedClause::Create(const ASTContext &C, Expr *Num, unsigned NumLoops, SourceLocation StartLoc, diff --git a/clang/lib/AST/ParentMap.cpp b/clang/lib/AST/ParentMap.cpp index e09b5bbe75f328..2ff5c9d8aeb578 100644 --- a/clang/lib/AST/ParentMap.cpp +++ b/clang/lib/AST/ParentMap.cpp @@ -83,6 +83,18 @@ static void BuildParentMap(MapTy& M, Stmt* S, } break; } + case Stmt::CapturedStmtClass: + for (Stmt *SubStmt : S->children()) { + if (SubStmt) { + M[SubStmt] = S; + BuildParentMap(M, SubStmt, OVMode); + } + } + if (Stmt *SubStmt = cast(S)->getCapturedStmt()) { + M[SubStmt] = S; + BuildParentMap(M, SubStmt, OVMode); + } + break; default: for (Stmt *SubStmt : S->children()) { if (SubStmt) { diff --git a/clang/lib/AST/ScanfFormatString.cpp b/clang/lib/AST/ScanfFormatString.cpp index 1a87de70f86b77..8d763f28e57fd2 100644 --- a/clang/lib/AST/ScanfFormatString.cpp +++ b/clang/lib/AST/ScanfFormatString.cpp @@ -142,7 +142,7 @@ static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H, } // Look for the length modifier. - if (ParseLengthModifier(FS, I, E, LO, /*scanf=*/true) && I == E) { + if (ParseLengthModifier(FS, I, E, LO, /*IsScanf=*/true) && I == E) { // No more characters left? H.HandleIncompleteSpecifier(Start, E - Start); return true; diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 733ca232dd0379..ed75a0b5bcd85e 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2276,60 +2276,16 @@ bool QualType::isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const { getObjCLifetime() != Qualifiers::OCL_Weak; } -namespace { -// Helper class that determines whether this is a type that is non-trivial to -// primitive copy or move, or is a struct type that has a field of such type. -template -struct IsNonTrivialCopyMoveVisitor - : CopiedTypeVisitor, IsMove, bool> { - using Super = - CopiedTypeVisitor, IsMove, bool>; - IsNonTrivialCopyMoveVisitor(const ASTContext &C) : Ctx(C) {} - void preVisit(QualType::PrimitiveCopyKind PCK, QualType QT) {} - - bool visitWithKind(QualType::PrimitiveCopyKind PCK, QualType QT) { - if (const auto *AT = this->Ctx.getAsArrayType(QT)) - return this->asDerived().visit(Ctx.getBaseElementType(AT)); - return Super::visitWithKind(PCK, QT); - } - - bool visitARCStrong(QualType QT) { return true; } - bool visitARCWeak(QualType QT) { return true; } - bool visitTrivial(QualType QT) { return false; } - // Volatile fields are considered trivial. - bool visitVolatileTrivial(QualType QT) { return false; } - - bool visitStruct(QualType QT) { - const RecordDecl *RD = QT->castAs()->getDecl(); - // We don't want to apply the C restriction in C++ because C++ - // (1) can apply the restriction at a finer grain by banning copying or - // destroying the union, and - // (2) allows users to override these restrictions by declaring explicit - // constructors/etc, which we're not proposing to add to C. - if (isa(RD)) - return false; - for (const FieldDecl *FD : RD->fields()) - if (this->asDerived().visit(FD->getType())) - return true; - return false; - } - - const ASTContext &Ctx; -}; +bool QualType::hasNonTrivialToPrimitiveDefaultInitializeCUnion(const RecordDecl *RD) { + return RD->hasNonTrivialToPrimitiveDefaultInitializeCUnion(); +} -} // namespace +bool QualType::hasNonTrivialToPrimitiveDestructCUnion(const RecordDecl *RD) { + return RD->hasNonTrivialToPrimitiveDestructCUnion(); +} -bool QualType::isNonTrivialPrimitiveCType(const ASTContext &Ctx) const { - if (isNonTrivialToPrimitiveDefaultInitialize()) - return true; - DestructionKind DK = isDestructedType(); - if (DK != DK_none && DK != DK_cxx_destructor) - return true; - if (IsNonTrivialCopyMoveVisitor(Ctx).visit(*this)) - return true; - if (IsNonTrivialCopyMoveVisitor(Ctx).visit(*this)) - return true; - return false; +bool QualType::hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD) { + return RD->hasNonTrivialToPrimitiveCopyCUnion(); } QualType::PrimitiveDefaultInitializeKind @@ -4124,7 +4080,7 @@ CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const { void clang::FixedPointValueToString(SmallVectorImpl &Str, llvm::APSInt Val, unsigned Scale) { FixedPointSemantics FXSema(Val.getBitWidth(), Scale, Val.isSigned(), - /*isSaturated=*/false, - /*hasUnsignedPadding=*/false); + /*IsSaturated=*/false, + /*HasUnsignedPadding=*/false); APFixedPoint(Val, FXSema).toString(Str); } diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp index 5c79ea37ab11d3..0c699571555d54 100644 --- a/clang/lib/AST/VTableBuilder.cpp +++ b/clang/lib/AST/VTableBuilder.cpp @@ -1272,7 +1272,7 @@ ThisAdjustment ItaniumVTableBuilder::ComputeThisAdjustment( // We don't have vcall offsets for this virtual base, go ahead and // build them. VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass, - /*FinalOverriders=*/nullptr, + /*Overriders=*/nullptr, BaseSubobject(Offset.VirtualBase, CharUnits::Zero()), /*BaseIsVirtual=*/true, @@ -2245,7 +2245,7 @@ ItaniumVTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, if (I != VirtualBaseClassOffsetOffsets.end()) return I->second; - VCallAndVBaseOffsetBuilder Builder(RD, RD, /*FinalOverriders=*/nullptr, + VCallAndVBaseOffsetBuilder Builder(RD, RD, /*Overriders=*/nullptr, BaseSubobject(RD, CharUnits::Zero()), /*BaseIsVirtual=*/false, /*OffsetInLayoutClass=*/CharUnits::Zero()); diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp index 7e636ed1f58898..576f86516017bf 100644 --- a/clang/lib/Analysis/BodyFarm.cpp +++ b/clang/lib/Analysis/BodyFarm.cpp @@ -293,7 +293,7 @@ static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M, return CXXOperatorCallExpr::Create( /*AstContext=*/C, OO_Call, callOperatorDeclRef, - /*args=*/CallArgs, + /*Args=*/CallArgs, /*QualType=*/C.VoidTy, /*ExprValueType=*/VK_RValue, /*SourceLocation=*/SourceLocation(), FPOptions()); @@ -465,10 +465,10 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { auto *Out = IfStmt::Create(C, SourceLocation(), /* IsConstexpr=*/false, - /* init=*/nullptr, - /* var=*/nullptr, - /* cond=*/FlagCheck, - /* then=*/M.makeCompound({CallbackCall, FlagAssignment})); + /* Init=*/nullptr, + /* Var=*/nullptr, + /* Cond=*/FlagCheck, + /* Then=*/M.makeCompound({CallbackCall, FlagAssignment})); return Out; } @@ -511,7 +511,7 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { CallExpr *CE = CallExpr::Create( /*ASTContext=*/C, /*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Block), - /*args=*/None, + /*Args=*/None, /*QualType=*/C.VoidTy, /*ExprValueType=*/VK_RValue, /*SourceLocation=*/SourceLocation()); @@ -549,10 +549,10 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { // (5) Create the 'if' statement. auto *If = IfStmt::Create(C, SourceLocation(), /* IsConstexpr=*/false, - /* init=*/nullptr, - /* var=*/nullptr, - /* cond=*/GuardCondition, - /* then=*/CS); + /* Init=*/nullptr, + /* Var=*/nullptr, + /* Cond=*/GuardCondition, + /* Then=*/CS); return If; } @@ -657,8 +657,8 @@ static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D) /// Construct the If. auto *If = IfStmt::Create(C, SourceLocation(), /* IsConstexpr=*/false, - /* init=*/nullptr, - /* var=*/nullptr, Comparison, Body, + /* Init=*/nullptr, + /* Var=*/nullptr, Comparison, Body, SourceLocation(), Else); return If; diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index f92d311111e7b6..0ed1e988a196ae 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -2931,8 +2931,8 @@ CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) { // Add the successors. If we know that specific branches are // unreachable, inform addSuccessor() of that knowledge. - addSuccessor(Block, ThenBlock, /* isReachable = */ !KnownVal.isFalse()); - addSuccessor(Block, ElseBlock, /* isReachable = */ !KnownVal.isTrue()); + addSuccessor(Block, ThenBlock, /* IsReachable = */ !KnownVal.isFalse()); + addSuccessor(Block, ElseBlock, /* IsReachable = */ !KnownVal.isTrue()); // Add the condition as the last statement in the new block. This may // create new blocks as the condition may contain control-flow. Any newly @@ -4746,8 +4746,9 @@ CFGBlock *CFGBuilder::VisitOMPExecutableDirective(OMPExecutableDirective *D, // Reverse the elements to process them in natural order. Iterators are not // bidirectional, so we need to create temp vector. - for (Stmt *S : llvm::reverse(llvm::to_vector<8>( - OMPExecutableDirective::used_clauses_children(D->clauses())))) { + SmallVector Used( + OMPExecutableDirective::used_clauses_children(D->clauses())); + for (Stmt *S : llvm::reverse(Used)) { assert(S && "Expected non-null used-in-clause child."); if (CFGBlock *R = Visit(S)) B = R; diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp index f189e5de498a15..e30e3753d19365 100644 --- a/clang/lib/Basic/DiagnosticIDs.cpp +++ b/clang/lib/Basic/DiagnosticIDs.cpp @@ -311,11 +311,9 @@ namespace clang { // Common Diagnostic implementation //===----------------------------------------------------------------------===// -DiagnosticIDs::DiagnosticIDs() { CustomDiagInfo = nullptr; } +DiagnosticIDs::DiagnosticIDs() {} -DiagnosticIDs::~DiagnosticIDs() { - delete CustomDiagInfo; -} +DiagnosticIDs::~DiagnosticIDs() {} /// getCustomDiagID - Return an ID for a diagnostic with the specified message /// and level. If this is the first request for this diagnostic, it is @@ -325,7 +323,7 @@ DiagnosticIDs::~DiagnosticIDs() { /// mapped to a unique DiagID. unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) { if (!CustomDiagInfo) - CustomDiagInfo = new diag::CustomDiagInfo(); + CustomDiagInfo.reset(new diag::CustomDiagInfo()); return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this); } diff --git a/clang/lib/Basic/FixedPoint.cpp b/clang/lib/Basic/FixedPoint.cpp index f049e6f64a502c..05600dfc6d2125 100644 --- a/clang/lib/Basic/FixedPoint.cpp +++ b/clang/lib/Basic/FixedPoint.cpp @@ -190,12 +190,12 @@ void APFixedPoint::toString(llvm::SmallVectorImpl &Str) const { llvm::APInt FractPartMask = llvm::APInt::getAllOnesValue(Scale).zext(Width); llvm::APInt RadixInt = llvm::APInt(Width, 10); - IntPart.toString(Str, /*radix=*/10); + IntPart.toString(Str, /*Radix=*/10); Str.push_back('.'); do { (FractPart * RadixInt) .lshr(Scale) - .toString(Str, /*radix=*/10, Val.isSigned()); + .toString(Str, /*Radix=*/10, Val.isSigned()); FractPart = (FractPart * RadixInt) & FractPartMask; } while (FractPart != 0); } diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index c7588aa796fe70..12b0305e707c93 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -329,7 +329,7 @@ void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo, LineTableInfo &SourceManager::getLineTable() { if (!LineTable) - LineTable = new LineTableInfo(); + LineTable.reset(new LineTableInfo()); return *LineTable; } @@ -345,8 +345,6 @@ SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, } SourceManager::~SourceManager() { - delete LineTable; - // Delete FileEntry objects corresponding to content caches. Since the actual // content cache objects are bump pointer allocated, we just have to run the // dtors, but we call the deallocate method for completeness. diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 6011ae17b78eae..74ac69ab8946a8 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -118,6 +118,28 @@ void AArch64TargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts, getTargetDefinesARMV81A(Opts, Builder); } +void AArch64TargetInfo::getTargetDefinesARMV83A(const LangOptions &Opts, + MacroBuilder &Builder) const { + Builder.defineMacro("__ARM_FEATURE_JCVT", "1"); + // Also include the Armv8.2 defines + getTargetDefinesARMV82A(Opts, Builder); +} + +void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts, + MacroBuilder &Builder) const { + // Also include the Armv8.3 defines + // FIXME: Armv8.4 makes some extensions mandatory. Handle them here. + getTargetDefinesARMV83A(Opts, Builder); +} + +void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts, + MacroBuilder &Builder) const { + // Also include the Armv8.4 defines + // FIXME: Armv8.5 makes some extensions mandatory. Handle them here. + getTargetDefinesARMV84A(Opts, Builder); +} + + void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { // Target identification. @@ -177,13 +199,13 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, if (FPU & SveMode) Builder.defineMacro("__ARM_FEATURE_SVE", "1"); - if (CRC) + if (HasCRC) Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); - if (Crypto) + if (HasCrypto) Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1"); - if (Unaligned) + if (HasUnaligned) Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1"); if ((FPU & NeonMode) && HasFullFP16) @@ -209,6 +231,15 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, case llvm::AArch64::ArchKind::ARMV8_2A: getTargetDefinesARMV82A(Opts, Builder); break; + case llvm::AArch64::ArchKind::ARMV8_3A: + getTargetDefinesARMV83A(Opts, Builder); + break; + case llvm::AArch64::ArchKind::ARMV8_4A: + getTargetDefinesARMV84A(Opts, Builder); + break; + case llvm::AArch64::ArchKind::ARMV8_5A: + getTargetDefinesARMV85A(Opts, Builder); + break; } // All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8) builtins work. @@ -232,13 +263,13 @@ bool AArch64TargetInfo::hasFeature(StringRef Feature) const { bool AArch64TargetInfo::handleTargetFeatures(std::vector &Features, DiagnosticsEngine &Diags) { FPU = FPUMode; - CRC = 0; - Crypto = 0; - Unaligned = 1; - HasFullFP16 = 0; - HasDotProd = 0; - HasFP16FML = 0; - HasMTE = 0; + HasCRC = false; + HasCrypto = false; + HasUnaligned = true; + HasFullFP16 = false; + HasDotProd = false; + HasFP16FML = false; + HasMTE = false; ArchKind = llvm::AArch64::ArchKind::ARMV8A; for (const auto &Feature : Features) { @@ -247,23 +278,29 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector &Features, if (Feature == "+sve") FPU |= SveMode; if (Feature == "+crc") - CRC = 1; + HasCRC = true; if (Feature == "+crypto") - Crypto = 1; + HasCrypto = true; if (Feature == "+strict-align") - Unaligned = 0; + HasUnaligned = false; if (Feature == "+v8.1a") ArchKind = llvm::AArch64::ArchKind::ARMV8_1A; if (Feature == "+v8.2a") ArchKind = llvm::AArch64::ArchKind::ARMV8_2A; + if (Feature == "+v8.3a") + ArchKind = llvm::AArch64::ArchKind::ARMV8_3A; + if (Feature == "+v8.4a") + ArchKind = llvm::AArch64::ArchKind::ARMV8_4A; + if (Feature == "+v8.5a") + ArchKind = llvm::AArch64::ArchKind::ARMV8_5A; if (Feature == "+fullfp16") - HasFullFP16 = 1; + HasFullFP16 = true; if (Feature == "+dotprod") - HasDotProd = 1; + HasDotProd = true; if (Feature == "+fp16fml") - HasFP16FML = 1; + HasFP16FML = true; if (Feature == "+mte") - HasMTE = 1; + HasMTE = true; } setDataLayout(); diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h index 0241b585c4d13d..5833c146003b0b 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -28,13 +28,14 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo { enum FPUModeEnum { FPUMode, NeonMode = (1 << 0), SveMode = (1 << 1) }; unsigned FPU; - unsigned CRC; - unsigned Crypto; - unsigned Unaligned; - unsigned HasFullFP16; - unsigned HasDotProd; - unsigned HasFP16FML; - unsigned HasMTE; + bool HasCRC; + bool HasCrypto; + bool HasUnaligned; + bool HasFullFP16; + bool HasDotProd; + bool HasFP16FML; + bool HasMTE; + llvm::AArch64::ArchKind ArchKind; static const Builtin::Info BuiltinInfo[]; @@ -59,6 +60,12 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo { MacroBuilder &Builder) const; void getTargetDefinesARMV82A(const LangOptions &Opts, MacroBuilder &Builder) const; + void getTargetDefinesARMV83A(const LangOptions &Opts, + MacroBuilder &Builder) const; + void getTargetDefinesARMV84A(const LangOptions &Opts, + MacroBuilder &Builder) const; + void getTargetDefinesARMV85A(const LangOptions &Opts, + MacroBuilder &Builder) const; void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index bd0ae600380926..2a773d9992869b 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -466,7 +466,9 @@ void PPCTargetInfo::adjust(LangOptions &Opts) { Opts.AltiVec = 1; TargetInfo::adjust(Opts); if (LongDoubleFormat != &llvm::APFloat::IEEEdouble()) - LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble(); + LongDoubleFormat = Opts.PPCIEEELongDouble + ? &llvm::APFloat::IEEEquad() + : &llvm::APFloat::PPCDoubleDouble(); } ArrayRef PPCTargetInfo::getTargetBuiltins() const { diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index f800bb0b25dac0..58272d14abd1f2 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -65,9 +65,18 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__riscv"); bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32"); - // TODO: modify when more code models and ABIs are supported. + // TODO: modify when more code models are supported. Builder.defineMacro("__riscv_cmodel_medlow"); - Builder.defineMacro("__riscv_float_abi_soft"); + + StringRef ABIName = getABI(); + if (ABIName == "ilp32f" || ABIName == "lp64f") + Builder.defineMacro("__riscv_float_abi_single"); + else if (ABIName == "ilp32d" || ABIName == "lp64d") + Builder.defineMacro("__riscv_float_abi_double"); + else if (ABIName == "ilp32e") + Builder.defineMacro("__riscv_abi_rve"); + else + Builder.defineMacro("__riscv_float_abi_soft"); if (HasM) { Builder.defineMacro("__riscv_mul"); diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index bc814b79ce5168..ce193feaeb980c 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -87,8 +87,7 @@ class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo { } bool setABI(const std::string &Name) override { - // TODO: support ilp32f and ilp32d ABIs. - if (Name == "ilp32") { + if (Name == "ilp32" || Name == "ilp32f" || Name == "ilp32d") { ABI = Name; return true; } @@ -105,8 +104,7 @@ class LLVM_LIBRARY_VISIBILITY RISCV64TargetInfo : public RISCVTargetInfo { } bool setABI(const std::string &Name) override { - // TODO: support lp64f and lp64d ABIs. - if (Name == "lp64") { + if (Name == "lp64" || Name == "lp64f" || Name == "lp64d") { ABI = Name; return true; } diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index 76d8ab8146ffbb..d618c90b05c02f 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -917,6 +917,11 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, DefineStd(Builder, "i386", Opts); } + Builder.defineMacro("__SEG_GS"); + Builder.defineMacro("__SEG_FS"); + Builder.defineMacro("__seg_gs", "__attribute__((address_space(256)))"); + Builder.defineMacro("__seg_fs", "__attribute__((address_space(257)))"); + // Subtarget options. // FIXME: We are hard-coding the tune parameters based on the CPU, but they // truly should be based on -mtune options. diff --git a/clang/lib/Basic/Version.cpp b/clang/lib/Basic/Version.cpp index 5fd12762b68933..d6564582e77268 100644 --- a/clang/lib/Basic/Version.cpp +++ b/clang/lib/Basic/Version.cpp @@ -136,6 +136,8 @@ std::string getClangToolFullVersion(StringRef ToolName) { } std::string getClangFullCPPVersion() { + // The version string we report in __VERSION__ is just a compacted version of + // the one we report on the command line. std::string buf; llvm::raw_string_ostream OS(buf); #ifdef CLANG_VENDOR diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 8499af07dbb7fc..497652e85b47ad 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -60,7 +60,6 @@ #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h" #include "llvm/Transforms/Instrumentation/InstrProfiling.h" #include "llvm/Transforms/Instrumentation/MemorySanitizer.h" -#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" @@ -196,8 +195,11 @@ static void addBoundsCheckingPass(const PassManagerBuilder &Builder, PM.add(createBoundsCheckingLegacyPass()); } -static SanitizerCoverageOptions -getSancovOptsFromCGOpts(const CodeGenOptions &CGOpts) { +static void addSanitizerCoveragePass(const PassManagerBuilder &Builder, + legacy::PassManagerBase &PM) { + const PassManagerBuilderWrapper &BuilderWrapper = + static_cast(Builder); + const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); SanitizerCoverageOptions Opts; Opts.CoverageType = static_cast(CGOpts.SanitizeCoverageType); @@ -213,17 +215,7 @@ getSancovOptsFromCGOpts(const CodeGenOptions &CGOpts) { Opts.Inline8bitCounters = CGOpts.SanitizeCoverageInline8bitCounters; Opts.PCTable = CGOpts.SanitizeCoveragePCTable; Opts.StackDepth = CGOpts.SanitizeCoverageStackDepth; - return Opts; -} - -static void addSanitizerCoveragePass(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - const PassManagerBuilderWrapper &BuilderWrapper = - static_cast(Builder); - const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts(); - auto Opts = getSancovOptsFromCGOpts(CGOpts); - PM.add(createModuleSanitizerCoverageLegacyPassPass(Opts)); - PM.add(createSanitizerCoverageLegacyPassPass(Opts)); + PM.add(createSanitizerCoverageModulePass(Opts)); } // Check if ASan should use GC-friendly instrumentation for globals. @@ -975,17 +967,6 @@ static void addSanitizersAtO0(ModulePassManager &MPM, if (LangOpts.Sanitize.has(SanitizerKind::Thread)) { MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass())); } - - if (LangOpts.Sanitize.has(SanitizerKind::HWAddress)) { - bool Recover = CodeGenOpts.SanitizeRecover.has(SanitizerKind::HWAddress); - MPM.addPass(createModuleToFunctionPassAdaptor( - HWAddressSanitizerPass(/*CompileKernel=*/false, Recover))); - } - - if (LangOpts.Sanitize.has(SanitizerKind::KernelHWAddress)) { - MPM.addPass(createModuleToFunctionPassAdaptor( - HWAddressSanitizerPass(/*CompileKernel=*/true, /*Recover=*/true))); - } } /// A clean version of `EmitAssembly` that uses the new pass manager. @@ -1143,21 +1124,6 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( EntryExitInstrumenterPass(/*PostInlining=*/false))); }); - if (CodeGenOpts.SanitizeCoverageType || - CodeGenOpts.SanitizeCoverageIndirectCalls || - CodeGenOpts.SanitizeCoverageTraceCmp) { - auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts); - PB.registerPipelineStartEPCallback( - [SancovOpts](ModulePassManager &MPM) { - MPM.addPass(ModuleSanitizerCoveragePass(SancovOpts)); - }); - PB.registerOptimizerLastEPCallback( - [SancovOpts](FunctionPassManager &FPM, - PassBuilder::OptimizationLevel Level) { - FPM.addPass(SanitizerCoveragePass(SancovOpts)); - }); - } - // Register callbacks to schedule sanitizer passes at the appropriate part of // the pipeline. // FIXME: either handle asan/the remaining sanitizers or error out @@ -1199,23 +1165,6 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( UseOdrIndicator)); }); } - if (LangOpts.Sanitize.has(SanitizerKind::HWAddress)) { - bool Recover = - CodeGenOpts.SanitizeRecover.has(SanitizerKind::HWAddress); - PB.registerOptimizerLastEPCallback( - [Recover](FunctionPassManager &FPM, - PassBuilder::OptimizationLevel Level) { - FPM.addPass(HWAddressSanitizerPass( - /*CompileKernel=*/false, Recover)); - }); - } - if (LangOpts.Sanitize.has(SanitizerKind::KernelHWAddress)) { - PB.registerOptimizerLastEPCallback( - [](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { - FPM.addPass(HWAddressSanitizerPass( - /*CompileKernel=*/true, /*Recover=*/true)); - }); - } if (Optional Options = getGCOVOptions(CodeGenOpts)) PB.registerPipelineStartEPCallback([Options](ModulePassManager &MPM) { MPM.addPass(GCOVProfilerPass(*Options)); @@ -1242,18 +1191,18 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( } } - if (CodeGenOpts.OptimizationLevel == 0) { - if (CodeGenOpts.SanitizeCoverageType || - CodeGenOpts.SanitizeCoverageIndirectCalls || - CodeGenOpts.SanitizeCoverageTraceCmp) { - auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts); - MPM.addPass(ModuleSanitizerCoveragePass(SancovOpts)); - MPM.addPass(createModuleToFunctionPassAdaptor( - SanitizerCoveragePass(SancovOpts))); - } + if (LangOpts.Sanitize.has(SanitizerKind::HWAddress)) { + bool Recover = CodeGenOpts.SanitizeRecover.has(SanitizerKind::HWAddress); + MPM.addPass(HWAddressSanitizerPass( + /*CompileKernel=*/false, Recover)); + } + if (LangOpts.Sanitize.has(SanitizerKind::KernelHWAddress)) { + MPM.addPass(HWAddressSanitizerPass( + /*CompileKernel=*/true, /*Recover=*/true)); + } + if (CodeGenOpts.OptimizationLevel == 0) addSanitizersAtO0(MPM, TargetTriple, LangOpts, CodeGenOpts); - } } // FIXME: We still use the legacy pass manager to do code generation. We diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index 7a26ae2fdfab88..68c8c641139f22 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -263,7 +263,7 @@ class CGBuilderTy : public CGBuilderBaseTy { Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name)); llvm::APInt Offset( DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, - /*IsSigned=*/true); + /*isSigned=*/true); if (!GEP->accumulateConstantOffset(DL, Offset)) llvm_unreachable("offset of GEP with constants is always computable"); return Address(GEP, Addr.getAlignment().alignmentAtOffset( diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 0a75c96a74b9cd..a300bab49f9c86 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -589,7 +589,7 @@ CodeGenFunction::emitBuiltinObjectSize(const Expr *E, unsigned Type, auto DIter = LocalDeclMap.find(D); assert(DIter != LocalDeclMap.end()); - return EmitLoadOfScalar(DIter->second, /*volatile=*/false, + return EmitLoadOfScalar(DIter->second, /*Volatile=*/false, getContext().getSizeType(), E->getBeginLoc()); } } @@ -719,7 +719,7 @@ static llvm::Value *EmitX86BitTestIntrinsic(CodeGenFunction &CGF, llvm::FunctionType::get(CGF.Int8Ty, {IntPtrType, IntType}, false); llvm::InlineAsm *IA = - llvm::InlineAsm::get(FTy, Asm, Constraints, /*SideEffects=*/true); + llvm::InlineAsm::get(FTy, Asm, Constraints, /*hasSideEffects=*/true); return CGF.Builder.CreateCall(IA, {BitBase, BitPos}); } @@ -1063,7 +1063,7 @@ Value *CodeGenFunction::EmitMSVCBuiltinExpr(MSVCIntrin BuiltinID, } llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, {Int32Ty}, false); llvm::InlineAsm *IA = - llvm::InlineAsm::get(FTy, Asm, Constraints, /*SideEffects=*/true); + llvm::InlineAsm::get(FTy, Asm, Constraints, /*hasSideEffects=*/true); llvm::AttributeList NoReturnAttr = llvm::AttributeList::get( getLLVMContext(), llvm::AttributeList::FunctionIndex, llvm::Attribute::NoReturn); @@ -5999,9 +5999,9 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, llvm::InlineAsm *Emit = IsThumb ? InlineAsm::get(FTy, ".inst.n 0x" + utohexstr(ZExtValue), "", - /*SideEffects=*/true) + /*hasSideEffects=*/true) : InlineAsm::get(FTy, ".inst 0x" + utohexstr(ZExtValue), "", - /*SideEffects=*/true); + /*hasSideEffects=*/true); return Builder.CreateCall(Emit); } @@ -6977,6 +6977,14 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, CGM.getIntrinsic(Intrinsic::bitreverse, Arg->getType()), Arg, "rbit"); } + if (BuiltinID == AArch64::BI__builtin_arm_jcvt) { + assert((getContext().getTypeSize(E->getType()) == 32) && + "__jcvt of unusual size!"); + llvm::Value *Arg = EmitScalarExpr(E->getArg(0)); + return Builder.CreateCall( + CGM.getIntrinsic(Intrinsic::aarch64_fjcvtzs), Arg); + } + if (BuiltinID == AArch64::BI__clear_cache) { assert(E->getNumArgs() == 2 && "__clear_cache takes 2 arguments"); const FunctionDecl *FD = E->getDirectCallee(); @@ -12120,7 +12128,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, // This syscall signals a driver assertion failure in x86 NT kernels. llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); llvm::InlineAsm *IA = - llvm::InlineAsm::get(FTy, "int $$0x2c", "", /*SideEffects=*/true); + llvm::InlineAsm::get(FTy, "int $$0x2c", "", /*hasSideEffects=*/true); llvm::AttributeList NoReturnAttr = llvm::AttributeList::get( getLLVMContext(), llvm::AttributeList::FunctionIndex, llvm::Attribute::NoReturn); @@ -12671,6 +12679,8 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, case AMDGPU::BI__builtin_amdgcn_ds_swizzle: return emitBinaryBuiltin(*this, E, Intrinsic::amdgcn_ds_swizzle); + case AMDGPU::BI__builtin_amdgcn_mov_dpp8: + return emitBinaryBuiltin(*this, E, Intrinsic::amdgcn_mov_dpp8); case AMDGPU::BI__builtin_amdgcn_mov_dpp: case AMDGPU::BI__builtin_amdgcn_update_dpp: { llvm::SmallVector Args; @@ -12736,6 +12746,10 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_fract); case AMDGPU::BI__builtin_amdgcn_lerp: return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_lerp); + case AMDGPU::BI__builtin_amdgcn_ubfe: + return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_ubfe); + case AMDGPU::BI__builtin_amdgcn_sbfe: + return emitTernaryBuiltin(*this, E, Intrinsic::amdgcn_sbfe); case AMDGPU::BI__builtin_amdgcn_uicmp: case AMDGPU::BI__builtin_amdgcn_uicmpl: case AMDGPU::BI__builtin_amdgcn_sicmp: @@ -13905,6 +13919,11 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_data_drop); return Builder.CreateCall(Callee, {Arg}); } + case WebAssembly::BI__builtin_wasm_tls_size: { + llvm::Type *ResultType = ConvertType(E->getType()); + Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_tls_size, ResultType); + return Builder.CreateCall(Callee); + } case WebAssembly::BI__builtin_wasm_throw: { Value *Tag = EmitScalarExpr(E->getArg(0)); Value *Obj = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index adaeacfe868e09..6d903a0d09e232 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -239,7 +239,7 @@ llvm::FunctionCallee CodeGenModule::getAddrAndTypeOfCXXStructor( llvm::Constant *Ptr = GetOrCreateLLVMFunction( getMangledName(GD), FnType, GD, /*ForVTable=*/false, DontDefer, - /*isThunk=*/false, /*ExtraAttrs=*/llvm::AttributeList(), IsForDefinition); + /*IsThunk=*/false, /*ExtraAttrs=*/llvm::AttributeList(), IsForDefinition); return {FnType, Ptr}; } diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index 9c3973fb9f1c48..041c0f8959fd7a 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -291,7 +291,7 @@ llvm::GlobalValue::LinkageTypes CGCXXABI::getCXXDestructorLinkage( GVALinkage Linkage, const CXXDestructorDecl *Dtor, CXXDtorType DT) const { // Delegate back to CGM by default. return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage, - /*isConstantVariable=*/false); + /*IsConstantVariable=*/false); } bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) { diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 705998d3b21613..5f1fb100748296 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1810,7 +1810,7 @@ void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone, void CodeGenModule::AddDefaultFnAttrs(llvm::Function &F) { llvm::AttrBuilder FuncAttrs; ConstructDefaultFnAttrList(F.getName(), F.hasOptNone(), - /* AttrOnCallsite = */ false, FuncAttrs); + /* AttrOnCallSite = */ false, FuncAttrs); F.addAttributes(llvm::AttributeList::FunctionIndex, FuncAttrs); } @@ -2490,7 +2490,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, assert(NumIRArgs == 1); auto AI = FnArgs[FirstIRArg]; AI->setName(Arg->getName() + ".coerce"); - CreateCoercedStore(AI, Ptr, /*DestIsVolatile=*/false, *this); + CreateCoercedStore(AI, Ptr, /*DstIsVolatile=*/false, *this); } // Match to what EmitParmDecl is expecting for this type. @@ -3537,7 +3537,7 @@ RValue CallArg::getRValue(CodeGenFunction &CGF) const { void CallArg::copyInto(CodeGenFunction &CGF, Address Addr) const { LValue Dst = CGF.MakeAddrLValue(Addr, Ty); if (!HasLV && RV.isScalar()) - CGF.EmitStoreOfScalar(RV.getScalarVal(), Dst, /*init=*/true); + CGF.EmitStoreOfScalar(RV.getScalarVal(), Dst, /*isInit=*/true); else if (!HasLV && RV.isComplex()) CGF.EmitStoreOfComplex(RV.getComplexVal(), Dst, /*init=*/true); else { diff --git a/clang/lib/CodeGen/CGCoroutine.cpp b/clang/lib/CodeGen/CGCoroutine.cpp index c529c4d900c97b..aee5a927a055bf 100644 --- a/clang/lib/CodeGen/CGCoroutine.cpp +++ b/clang/lib/CodeGen/CGCoroutine.cpp @@ -405,7 +405,7 @@ struct CallCoroEnd final : public EHScopeStack::Cleanup { if (Bundles.empty()) { // Otherwise, (landingpad model), create a conditional branch that leads // either to a cleanup block or a block with EH resume instruction. - auto *ResumeBB = CGF.getEHResumeBlock(/*cleanup=*/true); + auto *ResumeBB = CGF.getEHResumeBlock(/*isCleanup=*/true); auto *CleanupContBB = CGF.createBasicBlock("cleanup.cont"); CGF.Builder.CreateCondBr(CoroEnd, ResumeBB, CleanupContBB); CGF.EmitBlock(CleanupContBB); diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 739b2d858cb2ef..19a9e75cc5ac9f 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -176,7 +176,7 @@ void CodeGenFunction::EmitVarDecl(const VarDecl &D) { return; llvm::GlobalValue::LinkageTypes Linkage = - CGM.getLLVMLinkageVarDefinition(&D, /*isConstant=*/false); + CGM.getLLVMLinkageVarDefinition(&D, /*IsConstant=*/false); // FIXME: We need to force the emission/use of a guard variable for // some variables even if we can constant-evaluate them because diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index b03e3faeb33897..7a0605b8450ac2 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -14,6 +14,7 @@ #include "CGCXXABI.h" #include "CGObjCRuntime.h" #include "CGOpenMPRuntime.h" +#include "TargetInfo.h" #include "clang/Basic/CodeGenOptions.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Intrinsics.h" @@ -118,9 +119,22 @@ static void EmitDeclDestroy(CodeGenFunction &CGF, const VarDecl &D, CXXDestructorDecl *Dtor = Record->getDestructor(); Func = CGM.getAddrAndTypeOfCXXStructor(GlobalDecl(Dtor, Dtor_Complete)); - Argument = llvm::ConstantExpr::getBitCast( - Addr.getPointer(), CGF.getTypes().ConvertType(Type)->getPointerTo()); - + if (CGF.getContext().getLangOpts().OpenCL) { + auto DestAS = + CGM.getTargetCodeGenInfo().getAddrSpaceOfCxaAtexitPtrParam(); + auto DestTy = CGF.getTypes().ConvertType(Type)->getPointerTo( + CGM.getContext().getTargetAddressSpace(DestAS)); + auto SrcAS = D.getType().getQualifiers().getAddressSpace(); + if (DestAS == SrcAS) + Argument = llvm::ConstantExpr::getBitCast(Addr.getPointer(), DestTy); + else + // FIXME: On addr space mismatch we are passing NULL. The generation + // of the global destructor function should be adjusted accordingly. + Argument = llvm::ConstantPointerNull::get(DestTy); + } else { + Argument = llvm::ConstantExpr::getBitCast( + Addr.getPointer(), CGF.getTypes().ConvertType(Type)->getPointerTo()); + } // Otherwise, the standard logic requires a helper function. } else { Func = CodeGenFunction(CGM) @@ -355,6 +369,10 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrDestructFunction( !isInSanitizerBlacklist(SanitizerKind::KernelHWAddress, Fn, Loc)) Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress); + if (getLangOpts().Sanitize.has(SanitizerKind::MemTag) && + !isInSanitizerBlacklist(SanitizerKind::MemTag, Fn, Loc)) + Fn->addFnAttr(llvm::Attribute::SanitizeMemTag); + if (getLangOpts().Sanitize.has(SanitizerKind::Thread) && !isInSanitizerBlacklist(SanitizerKind::Thread, Fn, Loc)) Fn->addFnAttr(llvm::Attribute::SanitizeThread); diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 748029b860960d..3b7a88a0b76938 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -32,7 +32,7 @@ static llvm::FunctionCallee getFreeExceptionFn(CodeGenModule &CGM) { // void __cxa_free_exception(void *thrown_exception); llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); + llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*isVarArg=*/false); return CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception"); } @@ -41,7 +41,7 @@ static llvm::FunctionCallee getUnexpectedFn(CodeGenModule &CGM) { // void __cxa_call_unexpected(void *thrown_exception); llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); + llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*isVarArg=*/false); return CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected"); } @@ -50,7 +50,7 @@ llvm::FunctionCallee CodeGenModule::getTerminateFn() { // void __terminate(); llvm::FunctionType *FTy = - llvm::FunctionType::get(VoidTy, /*IsVarArgs=*/false); + llvm::FunctionType::get(VoidTy, /*isVarArg=*/false); StringRef name; @@ -75,7 +75,7 @@ llvm::FunctionCallee CodeGenModule::getTerminateFn() { static llvm::FunctionCallee getCatchallRethrowFn(CodeGenModule &CGM, StringRef Name) { llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); + llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*isVarArg=*/false); return CGM.CreateRuntimeFunction(FTy, Name); } diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 62d930ca8c455a..5a4b1188b71147 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -2031,7 +2031,7 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, // Cast the source to the storage type and shift it into place. SrcVal = Builder.CreateIntCast(SrcVal, Ptr.getElementType(), - /*IsSigned=*/false); + /*isSigned=*/false); llvm::Value *MaskedVal = SrcVal; // See if there are other bits in the bitfield's storage we'll need to load @@ -2611,7 +2611,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { // some reason; most likely, because it's in an outer function. } else if (VD->isStaticLocal()) { addr = Address(CGM.getOrCreateStaticVarDecl( - *VD, CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false)), + *VD, CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false)), getContext().getDeclAlign(VD)); // No other cases for now. @@ -2927,7 +2927,7 @@ enum class CheckRecoverableKind { static CheckRecoverableKind getRecoverableKind(SanitizerMask Kind) { assert(Kind.countPopulation() == 1); - if (Kind == SanitizerKind::Vptr) + if (Kind == SanitizerKind::Function || Kind == SanitizerKind::Vptr) return CheckRecoverableKind::AlwaysRecoverable; else if (Kind == SanitizerKind::Return || Kind == SanitizerKind::Unreachable) return CheckRecoverableKind::Unrecoverable; @@ -3749,7 +3749,7 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, Idx = Builder.CreateNSWMul(Idx, NumElements); EltPtr = emitArraySubscriptGEP(*this, Base, Idx, VLA->getElementType(), !getLangOpts().isSignedOverflowDefined(), - /*SignedIndices=*/false, E->getExprLoc()); + /*signedIndices=*/false, E->getExprLoc()); } else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) { // If this is A[i] where A is an array, the frontend will have decayed the // base to be a ArrayToPointerDecay implicit cast. While correct, it is @@ -3769,7 +3769,7 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, EltPtr = emitArraySubscriptGEP( *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, ResultExprTy, !getLangOpts().isSignedOverflowDefined(), - /*SignedIndices=*/false, E->getExprLoc()); + /*signedIndices=*/false, E->getExprLoc()); BaseInfo = ArrayLV.getBaseInfo(); TBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, ResultExprTy); } else { @@ -3778,7 +3778,7 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, IsLowerBound); EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy, !getLangOpts().isSignedOverflowDefined(), - /*SignedIndices=*/false, E->getExprLoc()); + /*signedIndices=*/false, E->getExprLoc()); } return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo, TBAAInfo); @@ -3892,6 +3892,23 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field) { return EmitLValueForField(LambdaLV, Field); } +/// Get the field index in the debug info. The debug info structure/union +/// will ignore the unnamed bitfields. +unsigned CodeGenFunction::getDebugInfoFIndex(const RecordDecl *Rec, + unsigned FieldIndex) { + unsigned I = 0, Skipped = 0; + + for (auto F : Rec->getDefinition()->fields()) { + if (I == FieldIndex) + break; + if (F->isUnnamedBitfield()) + Skipped++; + I++; + } + + return FieldIndex - Skipped; +} + /// Get the address of a zero-sized field within a record. The resulting /// address doesn't necessarily have the right type. static Address emitAddrOfZeroSizeField(CodeGenFunction &CGF, Address Base, @@ -3931,7 +3948,7 @@ static Address emitPreserveStructAccess(CodeGenFunction &CGF, Address base, CGF.CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field); return CGF.Builder.CreatePreserveStructAccessIndex( - base, idx, field->getFieldIndex(), DbgInfo); + base, idx, CGF.getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo); } static bool hasAnyVptr(const QualType Type, const ASTContext &Context) { @@ -4048,7 +4065,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, getContext().getRecordType(rec), rec->getLocation()); addr = Address( Builder.CreatePreserveUnionAccessIndex( - addr.getPointer(), field->getFieldIndex(), DbgInfo), + addr.getPointer(), getDebugInfoFIndex(rec, field->getFieldIndex()), DbgInfo), addr.getAlignment()); } } else { @@ -4867,7 +4884,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee E->getDirectCallee(), /*ParamsToSkip*/ 0, Order); const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionCall( - Args, FnType, /*isChainCall=*/Chain); + Args, FnType, /*ChainCall=*/Chain); // C99 6.5.2.2p6: // If the expression that denotes the called function has a type diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 25b0abbc03045e..8ad229fc0c362b 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -1277,7 +1277,7 @@ static RValue EmitNewDeleteCall(CodeGenFunction &CGF, CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(CalleeDecl)); RValue RV = CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall( - Args, CalleeType, /*chainCall=*/false), + Args, CalleeType, /*ChainCall=*/false), Callee, ReturnValueSlot(), Args, &CallOrInvoke); /// C++1y [expr.new]p10: diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index cc5c463224a14b..31cf2aef1ba0b7 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1878,7 +1878,7 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) { if (VD->isLocalVarDecl()) { return CGM.getOrCreateStaticVarDecl( - *VD, CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false)); + *VD, CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false)); } } } diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 37d8bd08db991f..1dd7ec52230ee2 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -3735,7 +3735,7 @@ void CodeGenModule::emitAtAvailableLinkGuard() { llvm::FunctionType *CheckFTy = llvm::FunctionType::get(VoidTy, {}, false); llvm::FunctionCallee CFLinkCheckFuncRef = CreateRuntimeFunction( CheckFTy, "__clang_at_available_requires_core_foundation_framework", - llvm::AttributeList(), /*IsLocal=*/true); + llvm::AttributeList(), /*Local=*/true); llvm::Function *CFLinkCheckFunc = cast(CFLinkCheckFuncRef.getCallee()->stripPointerCasts()); if (CFLinkCheckFunc->empty()) { diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index e3a9c0b0d63b46..27e7175da841f6 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -2898,7 +2898,7 @@ Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, getThreadID(CGF, SourceLocation()), CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, - /*IsSigned=*/false), + /*isSigned=*/false), getOrCreateInternalVariable( CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; return Address( @@ -5254,7 +5254,7 @@ void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, if (const auto *ASE = dyn_cast(E->IgnoreParenImpCasts())) { LValue UpAddrLVal = - CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false); + CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1); llvm::Value *LowIntPtr = @@ -6293,7 +6293,7 @@ llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); if (DelayedCreation) { CGF.EmitStoreOfScalar( - llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*IsSigned=*/true), + llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), FlagsLVal); } else CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType()); @@ -6649,7 +6649,7 @@ emitNumTeamsForTargetDirective(CodeGenFunction &CGF, CGF.EmitScalarExpr(NumTeams, /*IgnoreResultAssign*/ true); return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, - /*IsSigned=*/true); + /*isSigned=*/true); } return Bld.getInt32(0); } @@ -6673,7 +6673,7 @@ emitNumTeamsForTargetDirective(CodeGenFunction &CGF, CGF.EmitScalarExpr(NumTeams, /*IgnoreResultAssign*/ true); return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, - /*IsSigned=*/true); + /*isSigned=*/true); } return Bld.getInt32(0); } @@ -6801,7 +6801,7 @@ static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, } NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, - /*IsSigned=*/false); + /*isSigned=*/false); if (DefaultThreadLimitVal) NumThreads = CGF.Builder.CreateSelect( CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), @@ -6875,7 +6875,7 @@ emitNumThreadsForTargetDirective(CodeGenFunction &CGF, llvm::Value *ThreadLimit = CGF.EmitScalarExpr( ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); ThreadLimitVal = - Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false); + Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); } if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { @@ -6902,7 +6902,7 @@ emitNumThreadsForTargetDirective(CodeGenFunction &CGF, llvm::Value *ThreadLimit = CGF.EmitScalarExpr( ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); ThreadLimitVal = - Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false); + Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); } const CapturedStmt *CS = D.getInnermostCapturedStmt(); if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) @@ -6925,7 +6925,7 @@ emitNumThreadsForTargetDirective(CodeGenFunction &CGF, llvm::Value *ThreadLimit = CGF.EmitScalarExpr( ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); ThreadLimitVal = - Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false); + Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); } return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); case OMPD_target_parallel: @@ -6963,7 +6963,7 @@ emitNumThreadsForTargetDirective(CodeGenFunction &CGF, llvm::Value *ThreadLimit = CGF.EmitScalarExpr( ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); ThreadLimitVal = - Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false); + Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); } if (D.hasClausesOfKind()) { CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); @@ -6971,7 +6971,7 @@ emitNumThreadsForTargetDirective(CodeGenFunction &CGF, llvm::Value *NumThreads = CGF.EmitScalarExpr( NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); NumThreadsVal = - Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*IsSigned=*/false); + Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); ThreadLimitVal = ThreadLimitVal ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, ThreadLimitVal), @@ -7865,7 +7865,7 @@ class MappableExprsHandler { llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, - /*isSinged=*/false); + /*isSigned=*/false); Sizes.push_back(Size); // Map type is always TARGET_PARAM Types.push_back(OMP_MAP_TARGET_PARAM); @@ -8416,7 +8416,7 @@ class MappableExprsHandler { CGF.Builder.CreateMemCpy( CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(), Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), - CurSizes.back(), /*isVolatile=*/false); + CurSizes.back(), /*IsVolatile=*/false); // Use new global variable as the base pointers. CurBasePointers.push_back(Addr); CurPointers.push_back(Addr); diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index a5396a362f2229..e8fbca5108ade3 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -3603,7 +3603,7 @@ static void emitSimpleAtomicStore(CodeGenFunction &CGF, bool IsSeqCst, CGF.EmitAtomicStore(RVal, LVal, IsSeqCst ? llvm::AtomicOrdering::SequentiallyConsistent : llvm::AtomicOrdering::Monotonic, - LVal.isVolatile(), /*IsInit=*/false); + LVal.isVolatile(), /*isInit=*/false); } } @@ -4095,7 +4095,7 @@ static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, // Emit calculation of the iterations count. llvm::Value *NumIterations = CGF.EmitScalarExpr(D.getNumIterations()); NumIterations = CGF.Builder.CreateIntCast(NumIterations, CGF.Int64Ty, - /*IsSigned=*/false); + /*isSigned=*/false); return NumIterations; }; if (IsOffloadEntry) diff --git a/clang/lib/CodeGen/CodeGenABITypes.cpp b/clang/lib/CodeGen/CodeGenABITypes.cpp index c047587dc00c17..6b6a116cf259b6 100644 --- a/clang/lib/CodeGen/CodeGenABITypes.cpp +++ b/clang/lib/CodeGen/CodeGenABITypes.cpp @@ -59,7 +59,7 @@ CodeGen::arrangeFreeFunctionCall(CodeGenModule &CGM, FunctionType::ExtInfo info, RequiredArgs args) { return CGM.getTypes().arrangeLLVMFunctionInfo( - returnType, /*IsInstanceMethod=*/false, /*IsChainCall=*/false, argTypes, + returnType, /*instanceMethod=*/false, /*chainCall=*/false, argTypes, info, {}, args); } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 937648700a2e83..eafe26674434fd 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -696,6 +696,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, Fn->addFnAttr(llvm::Attribute::SanitizeAddress); if (SanOpts.hasOneOf(SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress)) Fn->addFnAttr(llvm::Attribute::SanitizeHWAddress); + if (SanOpts.has(SanitizerKind::MemTag)) + Fn->addFnAttr(llvm::Attribute::SanitizeMemTag); if (SanOpts.has(SanitizerKind::Thread)) Fn->addFnAttr(llvm::Attribute::SanitizeThread); if (SanOpts.hasOneOf(SanitizerKind::Memory | SanitizerKind::KernelMemory)) diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index a51a9711ff170d..06ef2dff7e9f5c 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -114,7 +114,7 @@ enum TypeEvaluationKind { SANITIZER_CHECK(DivremOverflow, divrem_overflow, 0) \ SANITIZER_CHECK(DynamicTypeCacheMiss, dynamic_type_cache_miss, 0) \ SANITIZER_CHECK(FloatCastOverflow, float_cast_overflow, 0) \ - SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 0) \ + SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 1) \ SANITIZER_CHECK(ImplicitConversion, implicit_conversion, 0) \ SANITIZER_CHECK(InvalidBuiltin, invalid_builtin, 0) \ SANITIZER_CHECK(LoadInvalidValue, load_invalid_value, 0) \ @@ -2652,6 +2652,9 @@ class CodeGenFunction : public CodeGenTypeCache { /// Converts Location to a DebugLoc, if debug information is enabled. llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location); + /// Get the record field index as represented in debug info. + unsigned getDebugInfoFIndex(const RecordDecl *Rec, unsigned FieldIndex); + //===--------------------------------------------------------------------===// // Declaration Emission diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index ea52f0c61fce62..6ff72ec045e627 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1199,7 +1199,7 @@ CodeGenModule::getFunctionLinkage(GlobalDecl GD) { return llvm::GlobalValue::InternalLinkage; } - return getLLVMLinkageForDeclarator(D, Linkage, /*isConstantVariable=*/false); + return getLLVMLinkageForDeclarator(D, Linkage, /*IsConstantVariable=*/false); } llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) { @@ -2239,9 +2239,11 @@ bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV, SourceLocation Loc, QualType Ty, StringRef Category) const { // For now globals can be blacklisted only in ASan and KASan. - const SanitizerMask EnabledAsanMask = LangOpts.Sanitize.Mask & + const SanitizerMask EnabledAsanMask = + LangOpts.Sanitize.Mask & (SanitizerKind::Address | SanitizerKind::KernelAddress | - SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress); + SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress | + SanitizerKind::MemTag); if (!EnabledAsanMask) return false; const auto &SanitizerBL = getContext().getSanitizerBlacklist(); @@ -3577,8 +3579,12 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D, llvm::Constant * CodeGenModule::CreateRuntimeVariable(llvm::Type *Ty, StringRef Name) { - auto *Ret = - GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), nullptr); + auto PtrTy = + getContext().getLangOpts().OpenCL + ? llvm::PointerType::get( + Ty, getContext().getTargetAddressSpace(LangAS::opencl_global)) + : llvm::PointerType::getUnqual(Ty); + auto *Ret = GetOrCreateLLVMGlobal(Name, PtrTy, nullptr); setDSOLocal(cast(Ret->stripPointerCasts())); return Ret; } diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index d900c7b2383786..6d18027f16a805 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -1281,7 +1281,7 @@ std::string getCoverageSection(const CodeGenModule &CGM) { std::string normalizeFilename(StringRef Filename) { llvm::SmallString<256> Path(Filename); llvm::sys::fs::make_absolute(Path); - llvm::sys::path::remove_dots(Path, /*remove_dot_dots=*/true); + llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true); return Path.str().str(); } diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index a12f08fbe9a302..7367ff37cf45c8 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -1138,7 +1138,7 @@ void ItaniumCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) { // void __cxa_rethrow(); llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false); + llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); llvm::FunctionCallee Fn = CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow"); @@ -1152,7 +1152,7 @@ static llvm::FunctionCallee getAllocateExceptionFn(CodeGenModule &CGM) { // void *__cxa_allocate_exception(size_t thrown_size); llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, /*IsVarArgs=*/false); + llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, /*isVarArg=*/false); return CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception"); } @@ -1163,7 +1163,7 @@ static llvm::FunctionCallee getThrowFn(CodeGenModule &CGM) { llvm::Type *Args[3] = { CGM.Int8PtrTy, CGM.Int8PtrTy, CGM.Int8PtrTy }; llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, Args, /*IsVarArgs=*/false); + llvm::FunctionType::get(CGM.VoidTy, Args, /*isVarArg=*/false); return CGM.CreateRuntimeFunction(FTy, "__cxa_throw"); } @@ -2284,8 +2284,19 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF, llvm::Type *dtorTy = llvm::FunctionType::get(CGF.VoidTy, CGF.Int8PtrTy, false)->getPointerTo(); + // Preserve address space of addr. + auto AddrAS = addr ? addr->getType()->getPointerAddressSpace() : 0; + auto AddrInt8PtrTy = + AddrAS ? CGF.Int8Ty->getPointerTo(AddrAS) : CGF.Int8PtrTy; + + // Create a variable that binds the atexit to this shared object. + llvm::Constant *handle = + CGF.CGM.CreateRuntimeVariable(CGF.Int8Ty, "__dso_handle"); + auto *GV = cast(handle->stripPointerCasts()); + GV->setVisibility(llvm::GlobalValue::HiddenVisibility); + // extern "C" int __cxa_atexit(void (*f)(void *), void *p, void *d); - llvm::Type *paramTys[] = { dtorTy, CGF.Int8PtrTy, CGF.Int8PtrTy }; + llvm::Type *paramTys[] = {dtorTy, AddrInt8PtrTy, handle->getType()}; llvm::FunctionType *atexitTy = llvm::FunctionType::get(CGF.IntTy, paramTys, false); @@ -2294,12 +2305,6 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF, if (llvm::Function *fn = dyn_cast(atexit.getCallee())) fn->setDoesNotThrow(); - // Create a variable that binds the atexit to this shared object. - llvm::Constant *handle = - CGF.CGM.CreateRuntimeVariable(CGF.Int8Ty, "__dso_handle"); - auto *GV = cast(handle->stripPointerCasts()); - GV->setVisibility(llvm::GlobalValue::HiddenVisibility); - if (!addr) // addr is null when we are trying to register a dtor annotated with // __attribute__((destructor)) in a constructor function. Using null here is @@ -2309,7 +2314,7 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF, llvm::Value *args[] = {llvm::ConstantExpr::getBitCast( cast(dtor.getCallee()), dtorTy), - llvm::ConstantExpr::getBitCast(addr, CGF.Int8PtrTy), + llvm::ConstantExpr::getBitCast(addr, AddrInt8PtrTy), handle}; CGF.EmitNounwindRuntimeCall(atexit, args); } @@ -2397,7 +2402,7 @@ static bool isThreadWrapperReplaceable(const VarDecl *VD, static llvm::GlobalValue::LinkageTypes getThreadLocalWrapperLinkage(const VarDecl *VD, CodeGen::CodeGenModule &CGM) { llvm::GlobalValue::LinkageTypes VarLinkage = - CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false); + CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); // For internal linkage variables, we don't need an external or weak wrapper. if (llvm::GlobalValue::isLocalLinkage(VarLinkage)) @@ -2775,7 +2780,7 @@ ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) { // RTTI, check if emitting vtables opportunistically need any adjustment. GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy, - /*Constant=*/true, + /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage, nullptr, Name); const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); @@ -3380,7 +3385,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name); llvm::GlobalVariable *GV = new llvm::GlobalVariable(M, Init->getType(), - /*Constant=*/true, Linkage, Init, Name); + /*isConstant=*/true, Linkage, Init, Name); // If there's already an old global variable, replace it with the new one. if (OldGV) { @@ -3901,7 +3906,7 @@ void ItaniumCXXABI::emitCXXStructor(GlobalDecl GD) { static llvm::FunctionCallee getBeginCatchFn(CodeGenModule &CGM) { // void *__cxa_begin_catch(void*); llvm::FunctionType *FTy = llvm::FunctionType::get( - CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); + CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false); return CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch"); } @@ -3909,7 +3914,7 @@ static llvm::FunctionCallee getBeginCatchFn(CodeGenModule &CGM) { static llvm::FunctionCallee getEndCatchFn(CodeGenModule &CGM) { // void __cxa_end_catch(); llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false); + llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false); return CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch"); } @@ -3917,7 +3922,7 @@ static llvm::FunctionCallee getEndCatchFn(CodeGenModule &CGM) { static llvm::FunctionCallee getGetExceptionPtrFn(CodeGenModule &CGM) { // void *__cxa_get_exception_ptr(void*); llvm::FunctionType *FTy = llvm::FunctionType::get( - CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); + CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false); return CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr"); } @@ -4191,9 +4196,9 @@ void ItaniumCXXABI::emitBeginCatch(CodeGenFunction &CGF, /// This code is used only in C++. static llvm::FunctionCallee getClangCallTerminateFn(CodeGenModule &CGM) { llvm::FunctionType *fnTy = - llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); + llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*isVarArg=*/false); llvm::FunctionCallee fnRef = CGM.CreateRuntimeFunction( - fnTy, "__clang_call_terminate", llvm::AttributeList(), /*IsLocal=*/true); + fnTy, "__clang_call_terminate", llvm::AttributeList(), /*Local=*/true); llvm::Function *fn = cast(fnRef.getCallee()->stripPointerCasts()); if (fn->empty()) { diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index c37bfe3a594409..a91a949d024f8b 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -352,7 +352,7 @@ class MicrosoftCXXABI : public CGCXXABI { ? llvm::GlobalValue::LinkOnceODRLinkage : llvm::GlobalValue::InternalLinkage; auto *VDispMap = new llvm::GlobalVariable( - CGM.getModule(), VDispMapTy, /*Constant=*/true, Linkage, + CGM.getModule(), VDispMapTy, /*isConstant=*/true, Linkage, /*Initializer=*/Init, MangledName); return VDispMap; } @@ -436,7 +436,7 @@ class MicrosoftCXXABI : public CGCXXABI { friend struct MSRTTIBuilder; bool isImageRelative() const { - return CGM.getTarget().getPointerWidth(/*AddressSpace=*/0) == 64; + return CGM.getTarget().getPointerWidth(/*AddrSpace=*/0) == 64; } // 5 routines for constructing the llvm types for MS RTTI structs. @@ -730,7 +730,7 @@ class MicrosoftCXXABI : public CGCXXABI { // which describes the exception. llvm::Type *Args[] = {CGM.Int8PtrTy, getThrowInfoType()->getPointerTo()}; llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, Args, /*IsVarArgs=*/false); + llvm::FunctionType::get(CGM.VoidTy, Args, /*isVarArg=*/false); llvm::FunctionCallee Throw = CGM.CreateRuntimeFunction(FTy, "_CxxThrowException"); // _CxxThrowException is stdcall on 32-bit x86 platforms. @@ -1313,7 +1313,7 @@ llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage( // The base destructor most closely tracks the user-declared constructor, so // we delegate back to the normal declarator case. return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage, - /*isConstantVariable=*/false); + /*IsConstantVariable=*/false); case Dtor_Complete: // The complete destructor is like an inline function, but it may be // imported and therefore must be exported as well. This requires changing @@ -2250,7 +2250,7 @@ static void emitGlobalDtorWithTLRegDtor(CodeGenFunction &CGF, const VarDecl &VD, // extern "C" int __tlregdtor(void (*f)(void)); llvm::FunctionType *TLRegDtorTy = llvm::FunctionType::get( - CGF.IntTy, DtorStub->getType(), /*IsVarArg=*/false); + CGF.IntTy, DtorStub->getType(), /*isVarArg=*/false); llvm::FunctionCallee TLRegDtor = CGF.CGM.CreateRuntimeFunction( TLRegDtorTy, "__tlregdtor", llvm::AttributeList(), /*Local=*/true); @@ -2291,7 +2291,7 @@ void MicrosoftCXXABI::EmitThreadLocalInitFuncs( // pointers at start-up time and, eventually, at thread-creation time. auto AddToXDU = [&CGM](llvm::Function *InitFunc) { llvm::GlobalVariable *InitFuncPtr = new llvm::GlobalVariable( - CGM.getModule(), InitFunc->getType(), /*IsConstant=*/true, + CGM.getModule(), InitFunc->getType(), /*isConstant=*/true, llvm::GlobalVariable::InternalLinkage, InitFunc, Twine(InitFunc->getName(), "$initializer$")); InitFuncPtr->setSection(".CRT$XDU"); @@ -2340,7 +2340,7 @@ static ConstantAddress getInitThreadEpochPtr(CodeGenModule &CGM) { return ConstantAddress(GV, Align); auto *GV = new llvm::GlobalVariable( CGM.getModule(), CGM.IntTy, - /*Constant=*/false, llvm::GlobalVariable::ExternalLinkage, + /*isConstant=*/false, llvm::GlobalVariable::ExternalLinkage, /*Initializer=*/nullptr, VarName, /*InsertBefore=*/nullptr, llvm::GlobalVariable::GeneralDynamicTLSModel); GV->setAlignment(Align.getQuantity()); @@ -3400,7 +3400,7 @@ static llvm::GlobalVariable *getTypeInfoVTable(CodeGenModule &CGM) { if (auto VTable = CGM.getModule().getNamedGlobal(MangledName)) return VTable; return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy, - /*Constant=*/true, + /*isConstant=*/true, llvm::GlobalVariable::ExternalLinkage, /*Initializer=*/nullptr, MangledName); } @@ -3580,7 +3580,7 @@ llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() { // Forward-declare the class hierarchy descriptor auto Type = ABI.getClassHierarchyDescriptorType(); - auto CHD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage, + auto CHD = new llvm::GlobalVariable(Module, Type, /*isConstant=*/true, Linkage, /*Initializer=*/nullptr, MangledName); if (CHD->isWeakForLinker()) @@ -3619,7 +3619,7 @@ MSRTTIBuilder::getBaseClassArray(SmallVectorImpl &Classes) { auto *ArrType = llvm::ArrayType::get(PtrType, Classes.size() + 1); auto *BCA = new llvm::GlobalVariable(Module, ArrType, - /*Constant=*/true, Linkage, + /*isConstant=*/true, Linkage, /*Initializer=*/nullptr, MangledName); if (BCA->isWeakForLinker()) BCA->setComdat(CGM.getModule().getOrInsertComdat(BCA->getName())); @@ -3661,7 +3661,7 @@ MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) { // Forward-declare the base class descriptor. auto Type = ABI.getBaseClassDescriptorType(); auto BCD = - new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage, + new llvm::GlobalVariable(Module, Type, /*isConstant=*/true, Linkage, /*Initializer=*/nullptr, MangledName); if (BCD->isWeakForLinker()) BCD->setComdat(CGM.getModule().getOrInsertComdat(BCD->getName())); @@ -3707,7 +3707,7 @@ MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo &Info) { // Forward-declare the complete object locator. llvm::StructType *Type = ABI.getCompleteObjectLocatorType(); - auto COL = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage, + auto COL = new llvm::GlobalVariable(Module, Type, /*isConstant=*/true, Linkage, /*Initializer=*/nullptr, MangledName); // Initialize the CompleteObjectLocator. @@ -3822,7 +3822,7 @@ llvm::Constant *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) { llvm::StructType *TypeDescriptorType = getTypeDescriptorType(TypeInfoString); auto *Var = new llvm::GlobalVariable( - CGM.getModule(), TypeDescriptorType, /*Constant=*/false, + CGM.getModule(), TypeDescriptorType, /*isConstant=*/false, getLinkageForRTTI(Type), llvm::ConstantStruct::get(TypeDescriptorType, Fields), MangledName); @@ -4061,7 +4061,7 @@ llvm::Constant *MicrosoftCXXABI::getCatchableType(QualType T, }; llvm::StructType *CTType = getCatchableTypeType(); auto *GV = new llvm::GlobalVariable( - CGM.getModule(), CTType, /*Constant=*/true, getLinkageForRTTI(T), + CGM.getModule(), CTType, /*isConstant=*/true, getLinkageForRTTI(T), llvm::ConstantStruct::get(CTType, Fields), MangledName); GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); GV->setSection(".xdata"); @@ -4179,7 +4179,7 @@ llvm::GlobalVariable *MicrosoftCXXABI::getCatchableTypeArray(QualType T) { getMangleContext().mangleCXXCatchableTypeArray(T, NumEntries, Out); } CTA = new llvm::GlobalVariable( - CGM.getModule(), CTAType, /*Constant=*/true, getLinkageForRTTI(T), + CGM.getModule(), CTAType, /*isConstant=*/true, getLinkageForRTTI(T), llvm::ConstantStruct::get(CTAType, Fields), MangledName); CTA->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); CTA->setSection(".xdata"); @@ -4248,7 +4248,7 @@ llvm::GlobalVariable *MicrosoftCXXABI::getThrowInfo(QualType T) { PointerToCatchableTypes // CatchableTypeArray }; auto *GV = new llvm::GlobalVariable( - CGM.getModule(), TIType, /*Constant=*/true, getLinkageForRTTI(T), + CGM.getModule(), TIType, /*isConstant=*/true, getLinkageForRTTI(T), llvm::ConstantStruct::get(TIType, Fields), StringRef(MangledName)); GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); GV->setSection(".xdata"); diff --git a/clang/lib/CodeGen/SanitizerMetadata.cpp b/clang/lib/CodeGen/SanitizerMetadata.cpp index 3211a3e74d255a..ebc9cd5529bc6f 100644 --- a/clang/lib/CodeGen/SanitizerMetadata.cpp +++ b/clang/lib/CodeGen/SanitizerMetadata.cpp @@ -20,14 +20,17 @@ using namespace CodeGen; SanitizerMetadata::SanitizerMetadata(CodeGenModule &CGM) : CGM(CGM) {} +static bool isAsanHwasanOrMemTag(const SanitizerSet& SS) { + return SS.hasOneOf(SanitizerKind::Address | SanitizerKind::KernelAddress | + SanitizerKind::HWAddress | SanitizerKind::KernelHWAddress | + SanitizerKind::MemTag); +} + void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, SourceLocation Loc, StringRef Name, QualType Ty, bool IsDynInit, bool IsBlacklisted) { - if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address | - SanitizerKind::KernelAddress | - SanitizerKind::HWAddress | - SanitizerKind::KernelHWAddress)) + if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize)) return; IsDynInit &= !CGM.isInSanitizerBlacklist(GV, Loc, Ty, "init"); IsBlacklisted |= CGM.isInSanitizerBlacklist(GV, Loc, Ty); @@ -58,10 +61,7 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, const VarDecl &D, bool IsDynInit) { - if (!CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address | - SanitizerKind::KernelAddress | - SanitizerKind::HWAddress | - SanitizerKind::KernelHWAddress)) + if (!isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize)) return; std::string QualName; llvm::raw_string_ostream OS(QualName); @@ -78,10 +78,7 @@ void SanitizerMetadata::reportGlobalToASan(llvm::GlobalVariable *GV, void SanitizerMetadata::disableSanitizerForGlobal(llvm::GlobalVariable *GV) { // For now, just make sure the global is not modified by the ASan // instrumentation. - if (CGM.getLangOpts().Sanitize.hasOneOf(SanitizerKind::Address | - SanitizerKind::KernelAddress | - SanitizerKind::HWAddress | - SanitizerKind::KernelHWAddress)) + if (isAsanHwasanOrMemTag(CGM.getLangOpts().Sanitize)) reportGlobalToASan(GV, SourceLocation(), "", QualType(), false, true); } diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 458b9a6025bfe3..1e1038dbfe953e 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -833,7 +833,7 @@ ABIArgInfo WebAssemblyABIInfo::classifyReturnType(QualType RetTy) const { Address WebAssemblyABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty) const { - return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*Indirect=*/ false, + return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*IsIndirect=*/ false, getContext().getTypeInfoInChars(Ty), CharUnits::fromQuantity(4), /*AllowHigherAlign=*/ true); @@ -9188,25 +9188,45 @@ static bool getTypeString(SmallStringEnc &Enc, const Decl *D, namespace { class RISCVABIInfo : public DefaultABIInfo { private: - unsigned XLen; // Size of the integer ('x') registers in bits. + // Size of the integer ('x') registers in bits. + unsigned XLen; + // Size of the floating point ('f') registers in bits. Note that the target + // ISA might have a wider FLen than the selected ABI (e.g. an RV32IF target + // with soft float ABI has FLen==0). + unsigned FLen; static const int NumArgGPRs = 8; + static const int NumArgFPRs = 8; + bool detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, + llvm::Type *&Field1Ty, + CharUnits &Field1Off, + llvm::Type *&Field2Ty, + CharUnits &Field2Off) const; public: - RISCVABIInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen) - : DefaultABIInfo(CGT), XLen(XLen) {} + RISCVABIInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen, unsigned FLen) + : DefaultABIInfo(CGT), XLen(XLen), FLen(FLen) {} // DefaultABIInfo's classifyReturnType and classifyArgumentType are // non-virtual, but computeInfo is virtual, so we overload it. void computeInfo(CGFunctionInfo &FI) const override; - ABIArgInfo classifyArgumentType(QualType Ty, bool IsFixed, - int &ArgGPRsLeft) const; + ABIArgInfo classifyArgumentType(QualType Ty, bool IsFixed, int &ArgGPRsLeft, + int &ArgFPRsLeft) const; ABIArgInfo classifyReturnType(QualType RetTy) const; Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty) const override; ABIArgInfo extendType(QualType Ty) const; + + bool detectFPCCEligibleStruct(QualType Ty, llvm::Type *&Field1Ty, + CharUnits &Field1Off, llvm::Type *&Field2Ty, + CharUnits &Field2Off, int &NeededArgGPRs, + int &NeededArgFPRs) const; + ABIArgInfo coerceAndExpandFPCCEligibleStruct(llvm::Type *Field1Ty, + CharUnits Field1Off, + llvm::Type *Field2Ty, + CharUnits Field2Off) const; }; } // end anonymous namespace @@ -9228,18 +9248,215 @@ void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const { // different for variadic arguments, we must also track whether we are // examining a vararg or not. int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs; + int ArgFPRsLeft = FLen ? NumArgFPRs : 0; int NumFixedArgs = FI.getNumRequiredArgs(); int ArgNum = 0; for (auto &ArgInfo : FI.arguments()) { bool IsFixed = ArgNum < NumFixedArgs; - ArgInfo.info = classifyArgumentType(ArgInfo.type, IsFixed, ArgGPRsLeft); + ArgInfo.info = + classifyArgumentType(ArgInfo.type, IsFixed, ArgGPRsLeft, ArgFPRsLeft); ArgNum++; } } +// Returns true if the struct is a potential candidate for the floating point +// calling convention. If this function returns true, the caller is +// responsible for checking that if there is only a single field then that +// field is a float. +bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, + llvm::Type *&Field1Ty, + CharUnits &Field1Off, + llvm::Type *&Field2Ty, + CharUnits &Field2Off) const { + bool IsInt = Ty->isIntegralOrEnumerationType(); + bool IsFloat = Ty->isRealFloatingType(); + + if (IsInt || IsFloat) { + uint64_t Size = getContext().getTypeSize(Ty); + if (IsInt && Size > XLen) + return false; + // Can't be eligible if larger than the FP registers. Half precision isn't + // currently supported on RISC-V and the ABI hasn't been confirmed, so + // default to the integer ABI in that case. + if (IsFloat && (Size > FLen || Size < 32)) + return false; + // Can't be eligible if an integer type was already found (int+int pairs + // are not eligible). + if (IsInt && Field1Ty && Field1Ty->isIntegerTy()) + return false; + if (!Field1Ty) { + Field1Ty = CGT.ConvertType(Ty); + Field1Off = CurOff; + return true; + } + if (!Field2Ty) { + Field2Ty = CGT.ConvertType(Ty); + Field2Off = CurOff; + return true; + } + return false; + } + + if (auto CTy = Ty->getAs()) { + if (Field1Ty) + return false; + QualType EltTy = CTy->getElementType(); + if (getContext().getTypeSize(EltTy) > FLen) + return false; + Field1Ty = CGT.ConvertType(EltTy); + Field1Off = CurOff; + assert(CurOff.isZero() && "Unexpected offset for first field"); + Field2Ty = Field1Ty; + Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy); + return true; + } + + if (const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) { + uint64_t ArraySize = ATy->getSize().getZExtValue(); + QualType EltTy = ATy->getElementType(); + CharUnits EltSize = getContext().getTypeSizeInChars(EltTy); + for (uint64_t i = 0; i < ArraySize; ++i) { + bool Ret = detectFPCCEligibleStructHelper(EltTy, CurOff, Field1Ty, + Field1Off, Field2Ty, Field2Off); + if (!Ret) + return false; + CurOff += EltSize; + } + return true; + } + + if (const auto *RTy = Ty->getAs()) { + // Structures with either a non-trivial destructor or a non-trivial + // copy constructor are not eligible for the FP calling convention. + if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT.getCXXABI())) + return false; + if (isEmptyRecord(getContext(), Ty, true)) + return true; + const RecordDecl *RD = RTy->getDecl(); + // Unions aren't eligible unless they're empty (which is caught above). + if (RD->isUnion()) + return false; + int ZeroWidthBitFieldCount = 0; + for (const FieldDecl *FD : RD->fields()) { + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); + uint64_t FieldOffInBits = Layout.getFieldOffset(FD->getFieldIndex()); + QualType QTy = FD->getType(); + if (FD->isBitField()) { + unsigned BitWidth = FD->getBitWidthValue(getContext()); + // Allow a bitfield with a type greater than XLen as long as the + // bitwidth is XLen or less. + if (getContext().getTypeSize(QTy) > XLen && BitWidth <= XLen) + QTy = getContext().getIntTypeForBitwidth(XLen, false); + if (BitWidth == 0) { + ZeroWidthBitFieldCount++; + continue; + } + } + + bool Ret = detectFPCCEligibleStructHelper( + QTy, CurOff + getContext().toCharUnitsFromBits(FieldOffInBits), + Field1Ty, Field1Off, Field2Ty, Field2Off); + if (!Ret) + return false; + + // As a quirk of the ABI, zero-width bitfields aren't ignored for fp+fp + // or int+fp structs, but are ignored for a struct with an fp field and + // any number of zero-width bitfields. + if (Field2Ty && ZeroWidthBitFieldCount > 0) + return false; + } + return Field1Ty != nullptr; + } + + return false; +} + +// Determine if a struct is eligible for passing according to the floating +// point calling convention (i.e., when flattened it contains a single fp +// value, fp+fp, or int+fp of appropriate size). If so, NeededArgFPRs and +// NeededArgGPRs are incremented appropriately. +bool RISCVABIInfo::detectFPCCEligibleStruct(QualType Ty, llvm::Type *&Field1Ty, + CharUnits &Field1Off, + llvm::Type *&Field2Ty, + CharUnits &Field2Off, + int &NeededArgGPRs, + int &NeededArgFPRs) const { + Field1Ty = nullptr; + Field2Ty = nullptr; + NeededArgGPRs = 0; + NeededArgFPRs = 0; + bool IsCandidate = detectFPCCEligibleStructHelper( + Ty, CharUnits::Zero(), Field1Ty, Field1Off, Field2Ty, Field2Off); + // Not really a candidate if we have a single int but no float. + if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy()) + return IsCandidate = false; + if (!IsCandidate) + return false; + if (Field1Ty && Field1Ty->isFloatingPointTy()) + NeededArgFPRs++; + else if (Field1Ty) + NeededArgGPRs++; + if (Field2Ty && Field2Ty->isFloatingPointTy()) + NeededArgFPRs++; + else if (Field2Ty) + NeededArgGPRs++; + return IsCandidate; +} + +// Call getCoerceAndExpand for the two-element flattened struct described by +// Field1Ty, Field1Off, Field2Ty, Field2Off. This method will create an +// appropriate coerceToType and unpaddedCoerceToType. +ABIArgInfo RISCVABIInfo::coerceAndExpandFPCCEligibleStruct( + llvm::Type *Field1Ty, CharUnits Field1Off, llvm::Type *Field2Ty, + CharUnits Field2Off) const { + SmallVector CoerceElts; + SmallVector UnpaddedCoerceElts; + if (!Field1Off.isZero()) + CoerceElts.push_back(llvm::ArrayType::get( + llvm::Type::getInt8Ty(getVMContext()), Field1Off.getQuantity())); + + CoerceElts.push_back(Field1Ty); + UnpaddedCoerceElts.push_back(Field1Ty); + + if (!Field2Ty) { + return ABIArgInfo::getCoerceAndExpand( + llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.isZero()), + UnpaddedCoerceElts[0]); + } + + CharUnits Field2Align = + CharUnits::fromQuantity(getDataLayout().getABITypeAlignment(Field2Ty)); + CharUnits Field1Size = + CharUnits::fromQuantity(getDataLayout().getTypeStoreSize(Field1Ty)); + CharUnits Field2OffNoPadNoPack = Field1Size.alignTo(Field2Align); + + CharUnits Padding = CharUnits::Zero(); + if (Field2Off > Field2OffNoPadNoPack) + Padding = Field2Off - Field2OffNoPadNoPack; + else if (Field2Off != Field2Align && Field2Off > Field1Size) + Padding = Field2Off - Field1Size; + + bool IsPacked = !Field2Off.isMultipleOf(Field2Align); + + if (!Padding.isZero()) + CoerceElts.push_back(llvm::ArrayType::get( + llvm::Type::getInt8Ty(getVMContext()), Padding.getQuantity())); + + CoerceElts.push_back(Field2Ty); + UnpaddedCoerceElts.push_back(Field2Ty); + + auto CoerceToType = + llvm::StructType::get(getVMContext(), CoerceElts, IsPacked); + auto UnpaddedCoerceToType = + llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked); + + return ABIArgInfo::getCoerceAndExpand(CoerceToType, UnpaddedCoerceToType); +} + ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, - int &ArgGPRsLeft) const { + int &ArgGPRsLeft, + int &ArgFPRsLeft) const { assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); Ty = useFirstFieldIfTransparentUnion(Ty); @@ -9257,6 +9474,42 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, return ABIArgInfo::getIgnore(); uint64_t Size = getContext().getTypeSize(Ty); + + // Pass floating point values via FPRs if possible. + if (IsFixed && Ty->isFloatingType() && FLen >= Size && ArgFPRsLeft) { + ArgFPRsLeft--; + return ABIArgInfo::getDirect(); + } + + // Complex types for the hard float ABI must be passed direct rather than + // using CoerceAndExpand. + if (IsFixed && Ty->isComplexType() && FLen && ArgFPRsLeft >= 2) { + QualType EltTy = Ty->getAs()->getElementType(); + if (getContext().getTypeSize(EltTy) <= FLen) { + ArgFPRsLeft -= 2; + return ABIArgInfo::getDirect(); + } + } + + if (IsFixed && FLen && Ty->isStructureOrClassType()) { + llvm::Type *Field1Ty = nullptr; + llvm::Type *Field2Ty = nullptr; + CharUnits Field1Off = CharUnits::Zero(); + CharUnits Field2Off = CharUnits::Zero(); + int NeededArgGPRs; + int NeededArgFPRs; + bool IsCandidate = + detectFPCCEligibleStruct(Ty, Field1Ty, Field1Off, Field2Ty, Field2Off, + NeededArgGPRs, NeededArgFPRs); + if (IsCandidate && NeededArgGPRs <= ArgGPRsLeft && + NeededArgFPRs <= ArgFPRsLeft) { + ArgGPRsLeft -= NeededArgGPRs; + ArgFPRsLeft -= NeededArgFPRs; + return coerceAndExpandFPCCEligibleStruct(Field1Ty, Field1Off, Field2Ty, + Field2Off); + } + } + uint64_t NeededAlign = getContext().getTypeAlign(Ty); bool MustUseStack = false; // Determine the number of GPRs needed to pass the current argument @@ -9315,10 +9568,12 @@ ABIArgInfo RISCVABIInfo::classifyReturnType(QualType RetTy) const { return ABIArgInfo::getIgnore(); int ArgGPRsLeft = 2; + int ArgFPRsLeft = FLen ? 2 : 0; // The rules for return and argument types are the same, so defer to // classifyArgumentType. - return classifyArgumentType(RetTy, /*IsFixed=*/true, ArgGPRsLeft); + return classifyArgumentType(RetTy, /*IsFixed=*/true, ArgGPRsLeft, + ArgFPRsLeft); } Address RISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, @@ -9353,8 +9608,9 @@ ABIArgInfo RISCVABIInfo::extendType(QualType Ty) const { namespace { class RISCVTargetCodeGenInfo : public TargetCodeGenInfo { public: - RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen) - : TargetCodeGenInfo(new RISCVABIInfo(CGT, XLen)) {} + RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen, + unsigned FLen) + : TargetCodeGenInfo(new RISCVABIInfo(CGT, XLen, FLen)) {} void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const override { @@ -9493,9 +9749,16 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { return SetCGInfo(new MSP430TargetCodeGenInfo(Types)); case llvm::Triple::riscv32: - return SetCGInfo(new RISCVTargetCodeGenInfo(Types, 32)); - case llvm::Triple::riscv64: - return SetCGInfo(new RISCVTargetCodeGenInfo(Types, 64)); + case llvm::Triple::riscv64: { + StringRef ABIStr = getTarget().getABI(); + unsigned XLen = getTarget().getPointerWidth(0); + unsigned ABIFLen = 0; + if (ABIStr.endswith("f")) + ABIFLen = 32; + else if (ABIStr.endswith("d")) + ABIFLen = 64; + return SetCGInfo(new RISCVTargetCodeGenInfo(Types, XLen, ABIFLen)); + } case llvm::Triple::systemz: { bool HasVector = getTarget().getABI() == "vector"; diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h index d7e9eee9c5b3e1..e1e90e73cb5876 100644 --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -267,6 +267,11 @@ class TargetCodeGenInfo { LangAS SrcAddr, LangAS DestAddr, llvm::Type *DestTy) const; + /// Get address space of pointer parameter for __cxa_atexit. + virtual LangAS getAddrSpaceOfCxaAtexitPtrParam() const { + return LangAS::Default; + } + /// Get the syncscope used in LLVM IR. virtual llvm::SyncScope::ID getLLVMSyncScopeID(const LangOptions &LangOpts, SyncScope Scope, diff --git a/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp b/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp index 986ebc5d95fab6..6d7d69da4db5a9 100644 --- a/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp +++ b/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -55,7 +56,10 @@ struct SemaphorePipe { }; void signal() { - ssize_t Result = llvm::sys::RetryAfterSignal(-1, write, FDWrite, "A", 1); +#ifndef NDEBUG + ssize_t Result = +#endif + llvm::sys::RetryAfterSignal(-1, write, FDWrite, "A", 1); assert(Result != -1); } ~SemaphorePipe() { @@ -220,8 +224,8 @@ void DirectoryWatcherLinux::InotifyPollingLoop() { // Multiple epoll_events can be received for a single file descriptor per // epoll_wait call. - for (const auto &EpollEvent : EpollEventBuffer) { - if (EpollEvent.data.fd == InotifyPollingStopSignal.FDRead) { + for (int i = 0; i < EpollWaitResult; ++i) { + if (EpollEventBuffer[i].data.fd == InotifyPollingStopSignal.FDRead) { StopWork(); return; } @@ -329,8 +333,12 @@ std::unique_ptr clang::DirectoryWatcher::create( const int InotifyWD = inotify_add_watch( InotifyFD, Path.str().c_str(), - IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_EXCL_UNLINK | IN_MODIFY | - IN_MOVED_FROM | IN_MOVE_SELF | IN_MOVED_TO | IN_ONLYDIR | IN_IGNORED); + IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY | + IN_MOVED_FROM | IN_MOVE_SELF | IN_MOVED_TO | IN_ONLYDIR | IN_IGNORED +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) + | IN_EXCL_UNLINK +#endif + ); if (InotifyWD == -1) return nullptr; diff --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp index 931dd19f04ae03..5f3026e6ce508b 100644 --- a/clang/lib/Driver/Compilation.cpp +++ b/clang/lib/Driver/Compilation.cpp @@ -153,30 +153,28 @@ int Compilation::ExecuteCommand(const Command &C, if ((getDriver().CCPrintOptions || getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) { raw_ostream *OS = &llvm::errs(); + std::unique_ptr OwnedStream; // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the // output stream. if (getDriver().CCPrintOptions && getDriver().CCPrintOptionsFilename) { std::error_code EC; - OS = new llvm::raw_fd_ostream(getDriver().CCPrintOptionsFilename, EC, - llvm::sys::fs::F_Append | - llvm::sys::fs::F_Text); + OwnedStream.reset(new llvm::raw_fd_ostream( + getDriver().CCPrintOptionsFilename, EC, + llvm::sys::fs::F_Append | llvm::sys::fs::F_Text)); if (EC) { getDriver().Diag(diag::err_drv_cc_print_options_failure) << EC.message(); FailingCommand = &C; - delete OS; return 1; } + OS = OwnedStream.get(); } if (getDriver().CCPrintOptions) *OS << "[Logging clang options]"; C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions); - - if (OS != &llvm::errs()) - delete OS; } std::string Error; diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 22f26d90bd7dd2..396ddf4dd81620 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -2119,6 +2119,12 @@ void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args, Diag(clang::diag::warn_drv_treating_input_as_cxx) << getTypeName(OldTy) << getTypeName(Ty); } + + // If running with -fthinlto-index=, extensions that normally identify + // native object files actually identify LLVM bitcode files. + if (Args.hasArgNoClaim(options::OPT_fthinlto_index_EQ) && + Ty == types::TY_Object) + Ty = types::TY_LLVM_BC; } // -ObjC and -ObjC++ override the default language, but only for "source @@ -4017,9 +4023,9 @@ InputInfo Driver::BuildJobsForActionNoCache( Input.claim(); if (Input.getOption().matches(options::OPT_INPUT)) { const char *Name = Input.getValue(); - return InputInfo(A, Name, /* BaseInput = */ Name); + return InputInfo(A, Name, /* _BaseInput = */ Name); } - return InputInfo(A, &Input, /* BaseInput = */ ""); + return InputInfo(A, &Input, /* _BaseInput = */ ""); } if (const BindArchAction *BAA = dyn_cast(A)) { diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 8d4b9fc85de232..6b6a9feec42c5f 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -31,7 +31,8 @@ static const SanitizerMask NeedsUbsanRt = static const SanitizerMask NeedsUbsanCxxRt = SanitizerKind::Vptr | SanitizerKind::CFI; static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr; -static const SanitizerMask NotAllowedWithMinimalRuntime = SanitizerKind::Vptr; +static const SanitizerMask NotAllowedWithMinimalRuntime = + SanitizerKind::Function | SanitizerKind::Vptr; static const SanitizerMask RequiresPIE = SanitizerKind::DataFlow | SanitizerKind::HWAddress | SanitizerKind::Scudo; static const SanitizerMask NeedsUnwindTables = @@ -40,7 +41,8 @@ static const SanitizerMask NeedsUnwindTables = static const SanitizerMask SupportsCoverage = SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress | - SanitizerKind::Memory | SanitizerKind::KernelMemory | SanitizerKind::Leak | + SanitizerKind::MemTag | SanitizerKind::Memory | + SanitizerKind::KernelMemory | SanitizerKind::Leak | SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | SanitizerKind::DataFlow | SanitizerKind::Fuzzer | @@ -122,6 +124,7 @@ static void addDefaultBlacklists(const Driver &D, SanitizerMask Kinds, SanitizerMask Mask; } Blacklists[] = {{"asan_blacklist.txt", SanitizerKind::Address}, {"hwasan_blacklist.txt", SanitizerKind::HWAddress}, + {"memtag_blacklist.txt", SanitizerKind::MemTag}, {"msan_blacklist.txt", SanitizerKind::Memory}, {"tsan_blacklist.txt", SanitizerKind::Thread}, {"dfsan_abilist.txt", SanitizerKind::DataFlow}, @@ -420,7 +423,11 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Leak | SanitizerKind::Thread | SanitizerKind::Memory | SanitizerKind::KernelAddress | - SanitizerKind::Scudo | SanitizerKind::SafeStack)}; + SanitizerKind::Scudo | SanitizerKind::SafeStack), + std::make_pair(SanitizerKind::MemTag, + SanitizerKind::Address | SanitizerKind::KernelAddress | + SanitizerKind::HWAddress | + SanitizerKind::KernelHWAddress)}; // Enable toolchain specific default sanitizers if not explicitly disabled. SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove; diff --git a/clang/lib/Driver/ToolChains/Arch/ARM.cpp b/clang/lib/Driver/ToolChains/Arch/ARM.cpp index 2e7562c6ee2723..d1db583e52802a 100644 --- a/clang/lib/Driver/ToolChains/Arch/ARM.cpp +++ b/clang/lib/Driver/ToolChains/Arch/ARM.cpp @@ -376,7 +376,11 @@ void arm::getARMTargetFeatures(const ToolChain &TC, Features.push_back( Args.MakeArgString((F.second ? "+" : "-") + F.first())); } else if (!CPUName.empty()) { - DecodeARMFeaturesFromCPU(D, CPUName, ExtensionFeatures); + // This sets the default features for the specified CPU. We certainly don't + // want to override the features that have been explicitly specified on the + // command line. Therefore, process them directly instead of appending them + // at the end later. + DecodeARMFeaturesFromCPU(D, CPUName, Features); } if (CPUArg) diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp index 2e75039bf0d65e..34be226b69e980 100644 --- a/clang/lib/Driver/ToolChains/Arch/X86.cpp +++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp @@ -135,7 +135,7 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple, if (ArchType == llvm::Triple::x86_64) { Features.push_back("+sse4.2"); Features.push_back("+popcnt"); - Features.push_back("+mcx16"); + Features.push_back("+cx16"); } else Features.push_back("+ssse3"); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index c84cb480f1a54b..cb861f27aedabc 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1803,12 +1803,21 @@ void Clang::AddPPCTargetArgs(const ArgList &Args, break; } - if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) - // The ppc64 linux abis are all "altivec" abis by default. Accept and ignore - // the option if given as we don't have backend support for any targets - // that don't use the altivec abi. - if (StringRef(A->getValue()) != "altivec") + bool IEEELongDouble = false; + for (const Arg *A : Args.filtered(options::OPT_mabi_EQ)) { + StringRef V = A->getValue(); + if (V == "ieeelongdouble") + IEEELongDouble = true; + else if (V == "ibmlongdouble") + IEEELongDouble = false; + else if (V != "altivec") + // The ppc64 linux abis are all "altivec" abis by default. Accept and ignore + // the option if given as we don't have backend support for any targets + // that don't use the altivec abi. ABIName = A->getValue(); + } + if (IEEELongDouble) + CmdArgs.push_back("-mabi=ieeelongdouble"); ppc::FloatABI FloatABI = ppc::getPPCFloatABI(getToolChain().getDriver(), Args); @@ -2962,7 +2971,7 @@ static void RenderObjCOptions(const ToolChain &TC, const Driver &D, // We default off for Objective-C, on for Objective-C++. if (Args.hasFlag(options::OPT_fobjc_arc_exceptions, options::OPT_fno_objc_arc_exceptions, - /*default=*/types::isCXX(Input.getType()))) + /*Default=*/types::isCXX(Input.getType()))) CmdArgs.push_back("-fobjc-arc-exceptions"); } @@ -3638,8 +3647,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (const Arg *A = Args.getLastArg(options::OPT_fthinlto_index_EQ)) { if (!types::isLLVMIR(Input.getType())) - D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) - << "-x ir"; + D.Diag(diag::err_drv_arg_requires_bitcode_input) << A->getAsString(Args); Args.AddLastArg(CmdArgs, options::OPT_fthinlto_index_EQ); } @@ -4741,7 +4749,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasFlag( options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit, !RawTriple.isOSWindows() && - RawTriple.getOS() != llvm::Triple::Solaris && TC.getArch() != llvm::Triple::xcore && ((RawTriple.getVendor() != llvm::Triple::MipsTechnologies) || RawTriple.hasEnvironment())) || @@ -5694,7 +5701,7 @@ static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) { // The default is that /GX is not specified. if (EHArgs.empty() && Args.hasFlag(options::OPT__SLASH_GX, options::OPT__SLASH_GX_, - /*default=*/false)) { + /*Default=*/false)) { EH.Synch = true; EH.NoUnwindC = true; } @@ -5763,13 +5770,13 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, // This controls whether or not we emit RTTI data for polymorphic types. if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR, - /*default=*/false)) + /*Default=*/false)) CmdArgs.push_back("-fno-rtti-data"); // This controls whether or not we emit stack-protector instrumentation. // In MSVC, Buffer Security Check (/GS) is on by default. if (Args.hasFlag(options::OPT__SLASH_GS, options::OPT__SLASH_GS_, - /*default=*/true)) { + /*Default=*/true)) { CmdArgs.push_back("-stack-protector"); CmdArgs.push_back(Args.MakeArgString(Twine(LangOptions::SSPStrong))); } diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index d0c9d7d396272e..99691cb43dc422 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1135,16 +1135,12 @@ bool tools::isObjCAutoRefCount(const ArgList &Args) { enum class LibGccType { UnspecifiedLibGcc, StaticLibGcc, SharedLibGcc }; -static LibGccType getLibGccType(const ArgList &Args) { - bool Static = Args.hasArg(options::OPT_static_libgcc) || - Args.hasArg(options::OPT_static) || - Args.hasArg(options::OPT_static_pie); - - bool Shared = Args.hasArg(options::OPT_shared_libgcc); - if (Shared) - return LibGccType::SharedLibGcc; - if (Static) +static LibGccType getLibGccType(const Driver &D, const ArgList &Args) { + if (Args.hasArg(options::OPT_static_libgcc) || + Args.hasArg(options::OPT_static) || Args.hasArg(options::OPT_static_pie)) return LibGccType::StaticLibGcc; + if (Args.hasArg(options::OPT_shared_libgcc) || D.CCCIsCXX()) + return LibGccType::SharedLibGcc; return LibGccType::UnspecifiedLibGcc; } @@ -1170,8 +1166,8 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D, UNW == ToolChain::UNW_None) return; - LibGccType LGT = getLibGccType(Args); - bool AsNeeded = D.CCCIsCC() && LGT == LibGccType::UnspecifiedLibGcc && + LibGccType LGT = getLibGccType(D, Args); + bool AsNeeded = LGT == LibGccType::UnspecifiedLibGcc && !TC.getTriple().isAndroid() && !TC.getTriple().isOSCygMing(); if (AsNeeded) CmdArgs.push_back("--as-needed"); @@ -1180,11 +1176,11 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D, case ToolChain::UNW_None: return; case ToolChain::UNW_Libgcc: { - LibGccType LGT = getLibGccType(Args); - if (LGT == LibGccType::UnspecifiedLibGcc || LGT == LibGccType::SharedLibGcc) - CmdArgs.push_back("-lgcc_s"); - else if (LGT == LibGccType::StaticLibGcc) + LibGccType LGT = getLibGccType(D, Args); + if (LGT == LibGccType::StaticLibGcc) CmdArgs.push_back("-lgcc_eh"); + else + CmdArgs.push_back("-lgcc_s"); break; } case ToolChain::UNW_CompilerRT: @@ -1198,17 +1194,11 @@ static void AddUnwindLibrary(const ToolChain &TC, const Driver &D, static void AddLibgcc(const ToolChain &TC, const Driver &D, ArgStringList &CmdArgs, const ArgList &Args) { - bool isAndroid = TC.getTriple().isAndroid(); - - LibGccType LGT = getLibGccType(Args); - bool LibGccFirst = (D.CCCIsCC() && LGT == LibGccType::UnspecifiedLibGcc) || - LGT == LibGccType::StaticLibGcc; - if (LibGccFirst) + LibGccType LGT = getLibGccType(D, Args); + if (LGT != LibGccType::SharedLibGcc) CmdArgs.push_back("-lgcc"); - AddUnwindLibrary(TC, D, CmdArgs, Args); - - if (!LibGccFirst) + if (LGT == LibGccType::SharedLibGcc) CmdArgs.push_back("-lgcc"); // According to Android ABI, we have to link with libdl if we are @@ -1216,7 +1206,7 @@ static void AddLibgcc(const ToolChain &TC, const Driver &D, // // NOTE: This fixes a link error on Android MIPS as well. The non-static // libgcc for MIPS relies on _Unwind_Find_FDE and dl_iterate_phdr from libdl. - if (isAndroid && getLibGccType(Args) != LibGccType::StaticLibGcc) + if (TC.getTriple().isAndroid() && LGT != LibGccType::StaticLibGcc) CmdArgs.push_back("-ldl"); } diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp index 2344a69adb9623..1f5ec9ebb16d5e 100644 --- a/clang/lib/Driver/ToolChains/Fuchsia.cpp +++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -192,6 +192,11 @@ Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple, // ASan has higher priority because we always want the instrumentated version. Multilibs.push_back(Multilib("asan", {}, {}, 2) .flag("+fsanitize=address")); + // Use the asan+noexcept variant with ASan and -fno-exceptions. + Multilibs.push_back(Multilib("asan+noexcept", {}, {}, 3) + .flag("+fsanitize=address") + .flag("-fexceptions") + .flag("+fno-exceptions")); Multilibs.FilterOut([&](const Multilib &M) { std::vector RD = FilePaths(M); return std::all_of(RD.begin(), RD.end(), [&](std::string P) { diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index b4e19b12c8d72b..d900508ad9385a 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -1026,6 +1026,8 @@ SanitizerMask Linux::getSupportedSanitizers() const { Res |= SanitizerKind::HWAddress; Res |= SanitizerKind::KernelHWAddress; } + if (IsAArch64) + Res |= SanitizerKind::MemTag; return Res; } diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp index 3a789627c5519e..6ed80a8f475237 100644 --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -626,11 +626,11 @@ std::unique_ptr visualstudio::Compiler::GetCommand( // FIXME: How can we ensure this stays in sync with relevant clang-cl options? if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR, - /*default=*/false)) + /*Default=*/false)) CmdArgs.push_back("/GR-"); if (Args.hasFlag(options::OPT__SLASH_GS_, options::OPT__SLASH_GS, - /*default=*/false)) + /*Default=*/false)) CmdArgs.push_back("/GS-"); if (Arg *A = Args.getLastArg(options::OPT_ffunction_sections, diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp index c65b7837395988..38f24d4cf7e74c 100644 --- a/clang/lib/Driver/ToolChains/Solaris.cpp +++ b/clang/lib/Driver/ToolChains/Solaris.cpp @@ -65,10 +65,6 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-Bdynamic"); if (Args.hasArg(options::OPT_shared)) { CmdArgs.push_back("-shared"); - } else { - CmdArgs.push_back("--dynamic-linker"); - CmdArgs.push_back( - Args.MakeArgString(getToolChain().GetFilePath("ld.so.1"))); } // libpthread has been folded into libc since Solaris 10, no need to do diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 6b698e24b5e508..490c4f46135e22 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -388,6 +388,10 @@ class AnnotatingParser { bool isCpp11AttributeSpecifier(const FormatToken &Tok) { if (!Style.isCpp() || !Tok.startsSequence(tok::l_square, tok::l_square)) return false; + // The first square bracket is part of an ObjC array literal + if (Tok.Previous && Tok.Previous->is(tok::at)) { + return false; + } const FormatToken *AttrTok = Tok.Next->Next; if (!AttrTok) return false; @@ -400,7 +404,7 @@ class AnnotatingParser { while (AttrTok && !AttrTok->startsSequence(tok::r_square, tok::r_square)) { // ObjC message send. We assume nobody will use : in a C++11 attribute // specifier parameter, although this is technically valid: - // [[foo(:)]] + // [[foo(:)]]. if (AttrTok->is(tok::colon) || AttrTok->startsSequence(tok::identifier, tok::identifier) || AttrTok->startsSequence(tok::r_paren, tok::identifier)) diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 36a18de0178685..3f3c80bc1ccf17 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -833,7 +833,7 @@ class NoLineBreakFormatter : public LineFormatter { LineState State = Indenter->getInitialState(FirstIndent, FirstStartColumn, &Line, DryRun); while (State.NextToken) { - formatChildren(State, /*Newline=*/false, DryRun, Penalty); + formatChildren(State, /*NewLine=*/false, DryRun, Penalty); Indenter->addTokenToState( State, /*Newline=*/State.NextToken->MustBreakBefore, DryRun); } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 7a07d9955fe74a..8a9844096f0816 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2745,6 +2745,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.LongDoubleSize = Args.hasArg(OPT_mlong_double_128) ? 128 : Args.hasArg(OPT_mlong_double_64) ? 64 : 0; + Opts.PPCIEEELongDouble = Args.hasArg(OPT_mabi_EQ_ieeelongdouble); Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); Opts.ROPI = Args.hasArg(OPT_fropi); Opts.RWPI = Args.hasArg(OPT_frwpi); diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 7d54d665146b67..e37afae5332a0f 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -139,7 +139,7 @@ GeneratePCHAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile, std::unique_ptr OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, /*RemoveFileOnSignal=*/false, InFile, - /*Extension=*/"", /*useTemporary=*/true); + /*Extension=*/"", /*UseTemporary=*/true); if (!OS) return nullptr; @@ -215,7 +215,7 @@ GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI, // We use a temporary to avoid race conditions. return CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, /*RemoveFileOnSignal=*/false, InFile, - /*Extension=*/"", /*useTemporary=*/true, + /*Extension=*/"", /*UseTemporary=*/true, /*CreateMissingDirectories=*/true); } diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index a02c266c094a89..3906e2ae1b9855 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -411,7 +411,7 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, if (LangOpts.OpenCLCPlusPlusVersion == 100) Builder.defineMacro("__OPENCL_CPP_VERSION__", "100"); else - llvm_unreachable("Unsupported OpenCL C++ version"); + llvm_unreachable("Unsupported C++ version for OpenCL"); Builder.defineMacro("__CL_CPP_VERSION_1_0__", "100"); } else { // OpenCL v1.0 and v1.1 do not have a predefined macro to indicate the @@ -604,6 +604,11 @@ static void InitializePredefinedMacros(const TargetInfo &TI, // Support for #pragma redefine_extname (Sun compatibility) Builder.defineMacro("__PRAGMA_REDEFINE_EXTNAME", "1"); + // Previously this macro was set to a string aiming to achieve compatibility + // with GCC 4.2.1. Now, just return the full Clang version + Builder.defineMacro("__VERSION__", "\"" + + Twine(getClangFullCPPVersion()) + "\""); + // Initialize language-specific preprocessor defines. // Standard conforming mode? diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp index 170149d5053fff..bd091ee0335128 100644 --- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -2428,7 +2428,7 @@ void RewriteModernObjC::SynthMsgSendFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2442,7 +2442,7 @@ void RewriteModernObjC::SynthMsgSendSuperFunctionDecl() { SmallVector ArgTys; ArgTys.push_back(Context->VoidTy); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2461,7 +2461,7 @@ void RewriteModernObjC::SynthMsgSendStretFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2477,7 +2477,7 @@ void RewriteModernObjC::SynthMsgSendSuperStretFunctionDecl() { SmallVector ArgTys; ArgTys.push_back(Context->VoidTy); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2497,7 +2497,7 @@ void RewriteModernObjC::SynthMsgSendFpretFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->DoubleTy, - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), diff --git a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp index 2ff230dfff1b58..05078baee790cc 100644 --- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -2335,7 +2335,7 @@ void RewriteObjC::SynthMsgSendFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2357,7 +2357,7 @@ void RewriteObjC::SynthMsgSendSuperFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2376,7 +2376,7 @@ void RewriteObjC::SynthMsgSendStretFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2400,7 +2400,7 @@ void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2420,7 +2420,7 @@ void RewriteObjC::SynthMsgSendFpretFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->DoubleTy, - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), diff --git a/clang/lib/Headers/arm_acle.h b/clang/lib/Headers/arm_acle.h index 08d65fa0d0696a..096cc261af2c62 100644 --- a/clang/lib/Headers/arm_acle.h +++ b/clang/lib/Headers/arm_acle.h @@ -597,6 +597,14 @@ __crc32cd(uint32_t __a, uint64_t __b) { } #endif +/* Armv8.3-A Javascript conversion intrinsic */ +#if __ARM_64BIT_STATE && defined(__ARM_FEATURE_JCVT) +static __inline__ int32_t __attribute__((__always_inline__, __nodebug__)) +__jcvt(double __a) { + return __builtin_arm_jcvt(__a); +} +#endif + /* 10.1 Special register intrinsics */ #define __arm_rsr(sysreg) __builtin_arm_rsr(sysreg) #define __arm_rsr64(sysreg) __builtin_arm_rsr64(sysreg) diff --git a/clang/lib/Headers/ppc_wrappers/mm_malloc.h b/clang/lib/Headers/ppc_wrappers/mm_malloc.h index 36589194b3e2f3..d91d7865c893c6 100644 --- a/clang/lib/Headers/ppc_wrappers/mm_malloc.h +++ b/clang/lib/Headers/ppc_wrappers/mm_malloc.h @@ -25,12 +25,8 @@ _mm_malloc (size_t size, size_t alignment) { /* PowerPC64 ELF V2 ABI requires quadword alignment. */ size_t vec_align = sizeof (__vector float); - /* Linux GLIBC malloc alignment is at least 2 X ptr size. */ - size_t malloc_align = (sizeof (void *) + sizeof (void *)); void *ptr; - if (alignment == malloc_align && alignment == vec_align) - return malloc (size); if (alignment < vec_align) alignment = vec_align; if (posix_memalign (&ptr, alignment, size) == 0) diff --git a/clang/lib/Index/IndexDecl.cpp b/clang/lib/Index/IndexDecl.cpp index e41b5fecdd24b0..5bbbb0d32bf457 100644 --- a/clang/lib/Index/IndexDecl.cpp +++ b/clang/lib/Index/IndexDecl.cpp @@ -416,7 +416,7 @@ class IndexingDeclVisitor : public ConstDeclVisitor { if (D->isThisDeclarationADefinition()) { TRY_DECL(D, IndexCtx.handleDecl(D)); TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, - /*superLoc=*/SourceLocation())); + /*SuperLoc=*/SourceLocation())); TRY_TO(IndexCtx.indexDeclContext(D)); } else { return IndexCtx.handleReference(D, D->getLocation(), nullptr, @@ -466,7 +466,7 @@ class IndexingDeclVisitor : public ConstDeclVisitor { CategoryLoc = D->getLocation(); TRY_TO(IndexCtx.handleDecl(D, CategoryLoc)); TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, - /*superLoc=*/SourceLocation())); + /*SuperLoc=*/SourceLocation())); TRY_TO(IndexCtx.indexDeclContext(D)); return true; } diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index ca94883ebecbb3..108630cc26f69a 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -539,7 +539,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); const FileEntry *FE = FileMgr.getFile(FrameworkName, - /*openFile=*/!SuggestedModule); + /*OpenFile=*/!SuggestedModule); if (!FE) { // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" const char *Private = "Private"; @@ -549,7 +549,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup( SearchPath->insert(SearchPath->begin()+OrigSize, Private, Private+strlen(Private)); - FE = FileMgr.getFile(FrameworkName, /*openFile=*/!SuggestedModule); + FE = FileMgr.getFile(FrameworkName, /*OpenFile=*/!SuggestedModule); } // If we found the header and are allowed to suggest a module, do so now. @@ -1047,7 +1047,7 @@ LookupSubframeworkHeader(StringRef Filename, } HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); - if (!(FE = FileMgr.getFile(HeadersFilename, /*openFile=*/true))) { + if (!(FE = FileMgr.getFile(HeadersFilename, /*OpenFile=*/true))) { // Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h" HeadersFilename = FrameworkName; HeadersFilename += "PrivateHeaders/"; @@ -1058,7 +1058,7 @@ LookupSubframeworkHeader(StringRef Filename, } HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end()); - if (!(FE = FileMgr.getFile(HeadersFilename, /*openFile=*/true))) + if (!(FE = FileMgr.getFile(HeadersFilename, /*OpenFile=*/true))) return nullptr; } diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 311c0e02fc6964..2756042f23eb20 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1419,7 +1419,7 @@ void Preprocessor::HandleMacroPublicDirective(Token &Tok) { // Note that this macro has now been exported. appendMacroDirective(II, AllocateVisibilityMacroDirective( - MacroNameTok.getLocation(), /*IsPublic=*/true)); + MacroNameTok.getLocation(), /*isPublic=*/true)); } /// Handle a #private directive. @@ -1446,7 +1446,7 @@ void Preprocessor::HandleMacroPrivateDirective() { // Note that this macro has now been marked private. appendMacroDirective(II, AllocateVisibilityMacroDirective( - MacroNameTok.getLocation(), /*IsPublic=*/false)); + MacroNameTok.getLocation(), /*isPublic=*/false)); } //===----------------------------------------------------------------------===// @@ -1937,7 +1937,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport( // and making the module loader convert it back again. ModuleLoadResult Imported = TheModuleLoader.loadModule( IncludeTok.getLocation(), Path, Module::Hidden, - /*IsIncludeDirective=*/true); + /*IsInclusionDirective=*/true); assert((Imported == nullptr || Imported == SuggestedModule.getModule()) && "the imported module is different than the suggested one"); diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 5021ff8aac52dc..687b9a9d3b7bdd 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -1707,7 +1707,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { HasLexedNextToken = Tok.is(tok::string_literal); if (!FinishLexStringLiteral(Tok, WarningName, "'__has_warning'", - /*MacroExpansion=*/false)) + /*AllowMacroExpansion=*/false)) return false; // FIXME: Should we accept "-R..." flags here, or should that be diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index e680e8d4bbd717..4e4db668551f8e 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -1191,7 +1191,7 @@ struct PragmaDiagnosticHandler : public PragmaHandler { std::string WarningName; if (!PP.FinishLexStringLiteral(Tok, WarningName, "pragma diagnostic", - /*MacroExpansion=*/false)) + /*AllowMacroExpansion=*/false)) return; if (Tok.isNot(tok::eod)) { @@ -1389,7 +1389,7 @@ struct PragmaExecCharsetHandler : public PragmaHandler { std::string ExecCharset; if (!PP.FinishLexStringLiteral(Tok, ExecCharset, "pragma execution_character_set", - /*MacroExpansion=*/false)) + /*AllowMacroExpansion=*/false)) return; // MSVC supports either of these, but nothing else. @@ -1490,7 +1490,7 @@ struct PragmaMessageHandler : public PragmaHandler { std::string MessageString; if (!PP.FinishLexStringLiteral(Tok, MessageString, PragmaKind(Kind), - /*MacroExpansion=*/true)) + /*AllowMacroExpansion=*/true)) return; if (ExpectClosingParen) { @@ -1540,7 +1540,7 @@ struct PragmaModuleImportHandler : public PragmaHandler { // If we have a non-empty module path, load the named module. Module *Imported = PP.getModuleLoader().loadModule(ImportLoc, ModuleName, Module::Hidden, - /*IsIncludeDirective=*/false); + /*IsInclusionDirective=*/false); if (!Imported) return; @@ -1666,7 +1666,7 @@ struct PragmaModuleLoadHandler : public PragmaHandler { // Load the module, don't make it visible. PP.getModuleLoader().loadModule(Loc, ModuleName, Module::Hidden, - /*IsIncludeDirective=*/false); + /*IsInclusionDirective=*/false); } }; diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index dd619389556998..bdc5fbcd2beab1 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -1263,7 +1263,7 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { Imported = TheModuleLoader.loadModule(ModuleImportLoc, ModuleImportPath, Module::Hidden, - /*IsIncludeDirective=*/false); + /*IsInclusionDirective=*/false); if (Imported) makeModuleVisible(Imported, SemiLoc); } diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 14151efd3d2a8e..a1abf8269c451b 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -1058,7 +1058,7 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, case CIK_DefaultArgument: bool InvalidAsDeclaration = false; Result = TryParseParameterDeclarationClause( - &InvalidAsDeclaration, /*VersusTemplateArgument=*/true); + &InvalidAsDeclaration, /*VersusTemplateArg=*/true); // If this is an expression or a declaration with a missing // 'typename', assume it's not a declaration. if (Result == TPResult::Ambiguous && InvalidAsDeclaration) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 0b57c8ab66345b..73b4f50fda4607 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3189,7 +3189,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, Actions.getTypeName(*Next.getIdentifierInfo(), Next.getLocation(), getCurScope(), &SS, false, false, nullptr, /*IsCtorOrDtorName=*/false, - /*WantNonTrivialSourceInfo=*/true, + /*WantNontrivialTypeSourceInfo=*/true, isClassTemplateDeductionContext(DSContext)); // If the referenced identifier is not a type, then this declspec is @@ -3559,7 +3559,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.setFunctionSpecInline(Loc, PrevSpec, DiagID); break; case tok::kw_virtual: - // OpenCL C++ v1.0 s2.9: the virtual function qualifier is not supported. + // C++ for OpenCL does not allow virtual function qualifier, to avoid + // function pointers restricted in OpenCL v2.0 s6.9.a. if (getLangOpts().OpenCLCPlusPlus) { DiagID = diag::err_openclcxx_virtual_function; PrevSpec = Tok.getIdentifierInfo()->getNameStart(); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 81a56a025048c0..9c61c4da447aab 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1208,9 +1208,9 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, // We have an identifier; check whether it is actually a type. IdentifierInfo *CorrectedII = nullptr; ParsedType Type = Actions.getTypeName( - *Id, IdLoc, getCurScope(), &SS, /*IsClassName=*/true, false, nullptr, + *Id, IdLoc, getCurScope(), &SS, /*isClassName=*/true, false, nullptr, /*IsCtorOrDtorName=*/false, - /*NonTrivialTypeSourceInfo=*/true, + /*WantNontrivialTypeSourceInfo=*/true, /*IsClassTemplateDeductionContext*/ false, &CorrectedII); if (!Type) { Diag(IdLoc, diag::err_expected_class_name); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index b5c01fe60fb04b..7a0c07bd3b04e6 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1770,7 +1770,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (Tok.is(tok::code_completion)) { tok::TokenKind CorrectedOpKind = OpKind == tok::arrow ? tok::period : tok::arrow; - ExprResult CorrectedLHS(/*IsInvalid=*/true); + ExprResult CorrectedLHS(/*Invalid=*/true); if (getLangOpts().CPlusPlus && OrigLHS) { const bool DiagsAreSuppressed = Diags.getSuppressAllDiagnostics(); Diags.setSuppressAllDiagnostics(true); @@ -2052,7 +2052,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { if (isCastExpr) return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(), ExprKind, - /*isType=*/true, + /*IsType=*/true, CastTy.getAsOpaquePtr(), CastRange); @@ -2063,7 +2063,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { if (!Operand.isInvalid()) Operand = Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(), ExprKind, - /*isType=*/false, + /*IsType=*/false, Operand.get(), CastRange); return Operand; @@ -3055,7 +3055,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { /*IsAmbiguous=*/false, /*RParenLoc=*/NoLoc, /*ArgInfo=*/nullptr, - /*NumArgs=*/0, + /*NumParams=*/0, /*EllipsisLoc=*/NoLoc, /*RParenLoc=*/NoLoc, /*RefQualifierIsLvalueRef=*/true, diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 9d296f18527dbc..85c7e6c6bcdf99 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -1334,10 +1334,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( SourceLocation NoLoc; D.AddTypeInfo(DeclaratorChunk::getFunction( - /*hasProto=*/true, - /*isAmbiguous=*/false, LParenLoc, ParamInfo.data(), + /*HasProto=*/true, + /*IsAmbiguous=*/false, LParenLoc, ParamInfo.data(), ParamInfo.size(), EllipsisLoc, RParenLoc, - /*RefQualifierIsLValueRef=*/true, + /*RefQualifierIsLvalueRef=*/true, /*RefQualifierLoc=*/NoLoc, MutableLoc, ESpecType, ESpecRange, DynamicExceptions.data(), DynamicExceptionRanges.data(), DynamicExceptions.size(), @@ -1394,14 +1394,14 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( SourceLocation NoLoc; D.AddTypeInfo(DeclaratorChunk::getFunction( - /*hasProto=*/true, - /*isAmbiguous=*/false, + /*HasProto=*/true, + /*IsAmbiguous=*/false, /*LParenLoc=*/NoLoc, /*Params=*/nullptr, /*NumParams=*/0, /*EllipsisLoc=*/NoLoc, /*RParenLoc=*/NoLoc, - /*RefQualifierIsLValueRef=*/true, + /*RefQualifierIsLvalueRef=*/true, /*RefQualifierLoc=*/NoLoc, MutableLoc, EST_None, /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, @@ -1701,7 +1701,7 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc, ParseUnqualifiedIdTemplateId(SS, SourceLocation(), Name, NameLoc, false, ObjectType, SecondTypeName, - /*AssumeTemplateName=*/true)) + /*AssumeTemplateId=*/true)) return ExprError(); return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, OpKind, @@ -3061,7 +3061,7 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { MaybeParseCXX11Attributes(Attrs); D.AddTypeInfo(DeclaratorChunk::getArray(0, - /*static=*/false, /*star=*/false, + /*isStatic=*/false, /*isStar=*/false, Size.get(), T.getOpenLocation(), T.getCloseLocation()), std::move(Attrs), T.getCloseLocation()); diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index a8d6f7fd602704..8937a0986c9562 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -3194,15 +3194,15 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, if (SuperLoc.isValid()) Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, KeyIdents, - /*AtArgumentEpression=*/true); + /*AtArgumentExpression=*/true); else if (ReceiverType) Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, KeyIdents, - /*AtArgumentEpression=*/true); + /*AtArgumentExpression=*/true); else Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr, KeyIdents, - /*AtArgumentEpression=*/true); + /*AtArgumentExpression=*/true); cutOffParsing(); return ExprError(); @@ -3232,15 +3232,15 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc, if (SuperLoc.isValid()) Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, KeyIdents, - /*AtArgumentEpression=*/false); + /*AtArgumentExpression=*/false); else if (ReceiverType) Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, KeyIdents, - /*AtArgumentEpression=*/false); + /*AtArgumentExpression=*/false); else Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr, KeyIdents, - /*AtArgumentEpression=*/false); + /*AtArgumentExpression=*/false); cutOffParsing(); return ExprError(); } diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 5b9749c80aa6d0..f81ecc738c283b 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -2491,7 +2491,7 @@ void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP, std::string NameString; if (!PP.LexStringLiteral(Tok, NameString, "pragma detect_mismatch", - /*MacroExpansion=*/true)) + /*AllowMacroExpansion=*/true)) return; // Read the comma followed by a second string literal. @@ -2502,7 +2502,7 @@ void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP, } if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch", - /*MacroExpansion=*/true)) + /*AllowMacroExpansion=*/true)) return; if (Tok.isNot(tok::r_paren)) { @@ -2584,7 +2584,7 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP, std::string ArgumentString; if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString, "pragma comment", - /*MacroExpansion=*/true)) + /*AllowMacroExpansion=*/true)) return; // FIXME: warn that 'exestr' is deprecated. diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 6ae75eda24312c..9bb5b6eac37e21 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -303,7 +303,7 @@ Decl *Parser::ParseSingleDeclarationAfterTemplate( return ParseFunctionDefinition( DeclaratorInfo, ParsedTemplateInfo(&FakedParamLists, /*isSpecialization=*/true, - /*LastParamListWasEmpty=*/true), + /*lastParameterListWasEmpty=*/true), &LateParsedAttrs); } } diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index 9433efb1819455..77e5eb09569303 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -596,7 +596,6 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc, // these storage-class specifiers. // OpenCL v1.2 s6.8 changes this to "The auto and register storage-class // specifiers are not supported." - // OpenCL C++ v1.0 s2.9 restricts register. if (S.getLangOpts().OpenCL && !S.getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers")) { switch (SC) { diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 3941643893af61..11fed28b52db09 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1658,12 +1658,24 @@ static void markEscapingByrefs(const FunctionScopeInfo &FSI, Sema &S) { // Set the EscapingByref flag of __block variables captured by // escaping blocks. for (const BlockDecl *BD : FSI.Blocks) { - if (BD->doesNotEscape()) - continue; for (const BlockDecl::Capture &BC : BD->captures()) { VarDecl *VD = BC.getVariable(); - if (VD->hasAttr()) + if (VD->hasAttr()) { + // Nothing to do if this is a __block variable captured by a + // non-escaping block. + if (BD->doesNotEscape()) + continue; VD->setEscapingByref(); + } + // Check whether the captured variable is or contains an object of + // non-trivial C union type. + QualType CapType = BC.getVariable()->getType(); + if (CapType.hasNonTrivialToPrimitiveDestructCUnion() || + CapType.hasNonTrivialToPrimitiveCopyCUnion()) + S.checkNonTrivialCUnion(BC.getVariable()->getType(), + BD->getCaretLocation(), + Sema::NTCUC_BlockCapture, + Sema::NTCUK_Destruct|Sema::NTCUK_Copy); } } diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 9ca6e4ab0e21ec..f184eda2f27382 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -285,7 +285,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, AngleBrackets)); case tok::kw_dynamic_cast: { - // OpenCL C++ 1.0 s2.9: dynamic_cast is not supported. + // dynamic_cast is not supported in C++ for OpenCL. if (getLangOpts().OpenCLCPlusPlus) { return ExprError(Diag(OpLoc, diag::err_openclcxx_not_supported) << "dynamic_cast"); @@ -2044,7 +2044,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, if (!CStyle) { Self.CheckCompatibleReinterpretCast(SrcType, DestType, - /*isDereference=*/false, OpRange); + /*IsDereference=*/false, OpRange); } // C++ 5.2.10p10: [...] a reference cast reinterpret_cast(x) has the @@ -2881,7 +2881,7 @@ ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc, Op.OpRange = SourceRange(LPLoc, CastExpr->getEndLoc()); if (getLangOpts().CPlusPlus) { - Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ false, + Op.CheckCXXCStyleCast(/*FunctionalCast=*/ false, isa(CastExpr)); } else { Op.CheckCStyleCast(); @@ -2908,7 +2908,7 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo, Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange(); Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getEndLoc()); - Op.CheckCXXCStyleCast(/*FunctionalStyle=*/true, /*ListInit=*/false); + Op.CheckCXXCStyleCast(/*FunctionalCast=*/true, /*ListInit=*/false); if (Op.SrcExpr.isInvalid()) return ExprError(); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 1c3d12ea0983a9..f9f82cdeef432b 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -11391,7 +11391,7 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, if (Overflowed) { S.DiagRuntimeBehavior(E->getExprLoc(), E, S.PDiag(diag::warn_impcast_fixed_point_range) - << Value.toString(/*radix=*/10) << T + << Value.toString(/*Radix=*/10) << T << E->getSourceRange() << clang::SourceRange(CC)); return; diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 7770f345cd0511..e4bbee86e3502d 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -5136,7 +5136,7 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, Decls.append(UME->decls_begin(), UME->decls_end()); const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase(); AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs, - /*SuppressUsedConversions=*/false, + /*SuppressUserConversions=*/false, /*PartialOverloading=*/true, FirstArgumentIsBase); } else { FunctionDecl *FD = nullptr; @@ -5151,7 +5151,7 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, else AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()), Args, CandidateSet, - /*SuppressUsedConversions=*/false, + /*SuppressUserConversions=*/false, /*PartialOverloading=*/true); } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) { @@ -5168,7 +5168,7 @@ QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, ArgExprs.append(Args.begin(), Args.end()); AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet, /*ExplicitArgs=*/nullptr, - /*SuppressUsedConversions=*/false, + /*SuppressUserConversions=*/false, /*PartialOverloading=*/true); } } else { @@ -5216,14 +5216,14 @@ QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type, if (auto *FD = dyn_cast(C)) { AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args, CandidateSet, - /*SuppressUsedConversions=*/false, + /*SuppressUserConversions=*/false, /*PartialOverloading=*/true, /*AllowExplicit*/ true); } else if (auto *FTD = dyn_cast(C)) { AddTemplateOverloadCandidate( FTD, DeclAccessPair::make(FTD, C->getAccess()), /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet, - /*SuppressUsedConversions=*/false, + /*SuppressUserConversions=*/false, /*PartialOverloading=*/true); } } @@ -8603,8 +8603,7 @@ void Sema::CodeCompletePreprocessorExpression() { if (!CodeCompleter || CodeCompleter->includeMacros()) AddMacroResults(PP, Results, - CodeCompleter ? CodeCompleter->loadExternal() : false, - true); + !CodeCompleter || CodeCompleter->loadExternal(), true); // defined () Results.EnterNewScope(); @@ -8801,8 +8800,7 @@ void Sema::GatherGlobalCodeCompletions( if (!CodeCompleter || CodeCompleter->includeMacros()) AddMacroResults(PP, Builder, - CodeCompleter ? CodeCompleter->loadExternal() : false, - true); + !CodeCompleter || CodeCompleter->loadExternal(), true); Results.clear(); Results.insert(Results.end(), Builder.data(), diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index b2a0632c6e7f1f..a6c52b7d4b2b8f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -22,6 +22,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/NonTrivialTypeVisitor.h" #include "clang/AST/StmtCXX.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/PartialDiagnostic.h" @@ -715,7 +716,7 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, getTypeName(*Corrected.getCorrectionAsIdentifierInfo(), IILoc, S, tmpSS.isSet() ? &tmpSS : SS, false, false, nullptr, /*IsCtorOrDtorName=*/false, - /*NonTrivialTypeSourceInfo=*/true); + /*WantNontrivialTypeSourceInfo=*/true); } return; } @@ -3164,7 +3165,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, // Calling Conventions on a Builtin aren't really useful and setting a // default calling convention and cdecl'ing some builtin redeclarations is // common, so warn and ignore the calling convention on the redeclaration. - Diag(New->getLocation(), diag::warn_cconv_ignored) + Diag(New->getLocation(), diag::warn_cconv_unsupported) << FunctionType::getNameForCallConv(NewTypeInfo.getCC()) << (int)CallingConventionIgnoredReason::BuiltinFunction; NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC()); @@ -6427,8 +6428,8 @@ NamedDecl *Sema::ActOnVariableDeclarator( } } - // OpenCL C++ 1.0 s2.9: the thread_local storage qualifier is not - // supported. OpenCL C does not support thread_local either, and + // C++ for OpenCL does not allow the thread_local storage qualifier. + // OpenCL C does not support thread_local either, and // also reject all other thread storage class specifiers. DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec(); if (TSC != TSCS_unspecified) { @@ -6504,6 +6505,11 @@ NamedDecl *Sema::ActOnVariableDeclarator( if (D.isInvalidType()) NewVD->setInvalidDecl(); + + if (NewVD->getType().hasNonTrivialToPrimitiveDestructCUnion() && + NewVD->hasLocalStorage()) + checkNonTrivialCUnion(NewVD->getType(), NewVD->getLocation(), + NTCUC_AutoVar, NTCUK_Destruct); } else { bool Invalid = false; @@ -7429,9 +7435,8 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { // OpenCL C v2.0 s6.5.1 - Variables defined at program scope and static // variables inside a function can also be declared in the global // address space. - // OpenCL C++ v1.0 s2.5 inherits rule from OpenCL C v2.0 and allows local - // address space additionally. - // FIXME: Add local AS for OpenCL C++. + // C++ for OpenCL inherits rule from OpenCL C v2.0. + // FIXME: Adding local AS in C++ for OpenCL might make sense. if (NewVD->isFileVarDecl() || NewVD->isStaticLocal() || NewVD->hasExternalStorage()) { if (!T->isSamplerT() && @@ -7485,7 +7490,10 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { return; } } - } else if (T.getAddressSpace() != LangAS::opencl_private) { + } else if (T.getAddressSpace() != LangAS::opencl_private && + // If we are parsing a template we didn't deduce an addr + // space yet. + T.getAddressSpace() != LangAS::Default) { // Do not allow other address spaces on automatic variable. Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl) << 1; NewVD->setInvalidDecl(); @@ -8924,6 +8932,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, << FunctionType::getNameForCallConv(CC); } } + + if (NewFD->getReturnType().hasNonTrivialToPrimitiveDestructCUnion() || + NewFD->getReturnType().hasNonTrivialToPrimitiveCopyCUnion()) + checkNonTrivialCUnion(NewFD->getReturnType(), + NewFD->getReturnTypeSourceRange().getBegin(), + NTCUC_FunctionReturn, NTCUK_Destruct|NTCUK_Copy); } else { // C++11 [replacement.functions]p3: // The program's definitions shall not be specified as inline. @@ -11070,6 +11084,264 @@ bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit, return VDecl->isInvalidDecl(); } +void Sema::checkNonTrivialCUnionInInitializer(const Expr *Init, + SourceLocation Loc) { + if (auto *CE = dyn_cast(Init)) + Init = CE->getSubExpr(); + + QualType InitType = Init->getType(); + assert((InitType.hasNonTrivialToPrimitiveDefaultInitializeCUnion() || + InitType.hasNonTrivialToPrimitiveCopyCUnion()) && + "shouldn't be called if type doesn't have a non-trivial C struct"); + if (auto *ILE = dyn_cast(Init)) { + for (auto I : ILE->inits()) { + if (!I->getType().hasNonTrivialToPrimitiveDefaultInitializeCUnion() && + !I->getType().hasNonTrivialToPrimitiveCopyCUnion()) + continue; + SourceLocation SL = I->getExprLoc(); + checkNonTrivialCUnionInInitializer(I, SL.isValid() ? SL : Loc); + } + return; + } + + if (isa(Init)) { + if (InitType.hasNonTrivialToPrimitiveDefaultInitializeCUnion()) + checkNonTrivialCUnion(InitType, Loc, NTCUC_DefaultInitializedObject, + NTCUK_Init); + } else { + // Assume all other explicit initializers involving copying some existing + // object. + // TODO: ignore any explicit initializers where we can guarantee + // copy-elision. + if (InitType.hasNonTrivialToPrimitiveCopyCUnion()) + checkNonTrivialCUnion(InitType, Loc, NTCUC_CopyInit, NTCUK_Copy); + } +} + +namespace { + +struct DiagNonTrivalCUnionDefaultInitializeVisitor + : DefaultInitializedTypeVisitor { + using Super = + DefaultInitializedTypeVisitor; + + DiagNonTrivalCUnionDefaultInitializeVisitor( + QualType OrigTy, SourceLocation OrigLoc, + Sema::NonTrivialCUnionContext UseContext, Sema &S) + : OrigTy(OrigTy), OrigLoc(OrigLoc), UseContext(UseContext), S(S) {} + + void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType QT, + const FieldDecl *FD, bool InNonTrivialUnion) { + if (const auto *AT = S.Context.getAsArrayType(QT)) + return this->asDerived().visit(S.Context.getBaseElementType(AT), FD, + InNonTrivialUnion); + return Super::visitWithKind(PDIK, QT, FD, InNonTrivialUnion); + } + + void visitARCStrong(QualType QT, const FieldDecl *FD, + bool InNonTrivialUnion) { + if (InNonTrivialUnion) + S.Diag(FD->getLocation(), diag::note_non_trivial_c_union) + << 1 << 0 << QT << FD->getName(); + } + + void visitARCWeak(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) { + if (InNonTrivialUnion) + S.Diag(FD->getLocation(), diag::note_non_trivial_c_union) + << 1 << 0 << QT << FD->getName(); + } + + void visitStruct(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) { + const RecordDecl *RD = QT->castAs()->getDecl(); + if (RD->isUnion()) { + if (OrigLoc.isValid()) { + bool IsUnion = false; + if (auto *OrigRD = OrigTy->getAsRecordDecl()) + IsUnion = OrigRD->isUnion(); + S.Diag(OrigLoc, diag::err_non_trivial_c_union_in_invalid_context) + << 0 << OrigTy << IsUnion << UseContext; + // Reset OrigLoc so that this diagnostic is emitted only once. + OrigLoc = SourceLocation(); + } + InNonTrivialUnion = true; + } + + if (InNonTrivialUnion) + S.Diag(RD->getLocation(), diag::note_non_trivial_c_union) + << 0 << 0 << QT.getUnqualifiedType() << ""; + + for (const FieldDecl *FD : RD->fields()) + asDerived().visit(FD->getType(), FD, InNonTrivialUnion); + } + + void visitTrivial(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {} + + // The non-trivial C union type or the struct/union type that contains a + // non-trivial C union. + QualType OrigTy; + SourceLocation OrigLoc; + Sema::NonTrivialCUnionContext UseContext; + Sema &S; +}; + +struct DiagNonTrivalCUnionDestructedTypeVisitor + : DestructedTypeVisitor { + using Super = + DestructedTypeVisitor; + + DiagNonTrivalCUnionDestructedTypeVisitor( + QualType OrigTy, SourceLocation OrigLoc, + Sema::NonTrivialCUnionContext UseContext, Sema &S) + : OrigTy(OrigTy), OrigLoc(OrigLoc), UseContext(UseContext), S(S) {} + + void visitWithKind(QualType::DestructionKind DK, QualType QT, + const FieldDecl *FD, bool InNonTrivialUnion) { + if (const auto *AT = S.Context.getAsArrayType(QT)) + return this->asDerived().visit(S.Context.getBaseElementType(AT), FD, + InNonTrivialUnion); + return Super::visitWithKind(DK, QT, FD, InNonTrivialUnion); + } + + void visitARCStrong(QualType QT, const FieldDecl *FD, + bool InNonTrivialUnion) { + if (InNonTrivialUnion) + S.Diag(FD->getLocation(), diag::note_non_trivial_c_union) + << 1 << 1 << QT << FD->getName(); + } + + void visitARCWeak(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) { + if (InNonTrivialUnion) + S.Diag(FD->getLocation(), diag::note_non_trivial_c_union) + << 1 << 1 << QT << FD->getName(); + } + + void visitStruct(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) { + const RecordDecl *RD = QT->castAs()->getDecl(); + if (RD->isUnion()) { + if (OrigLoc.isValid()) { + bool IsUnion = false; + if (auto *OrigRD = OrigTy->getAsRecordDecl()) + IsUnion = OrigRD->isUnion(); + S.Diag(OrigLoc, diag::err_non_trivial_c_union_in_invalid_context) + << 1 << OrigTy << IsUnion << UseContext; + // Reset OrigLoc so that this diagnostic is emitted only once. + OrigLoc = SourceLocation(); + } + InNonTrivialUnion = true; + } + + if (InNonTrivialUnion) + S.Diag(RD->getLocation(), diag::note_non_trivial_c_union) + << 0 << 1 << QT.getUnqualifiedType() << ""; + + for (const FieldDecl *FD : RD->fields()) + asDerived().visit(FD->getType(), FD, InNonTrivialUnion); + } + + void visitTrivial(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {} + void visitCXXDestructor(QualType QT, const FieldDecl *FD, + bool InNonTrivialUnion) {} + + // The non-trivial C union type or the struct/union type that contains a + // non-trivial C union. + QualType OrigTy; + SourceLocation OrigLoc; + Sema::NonTrivialCUnionContext UseContext; + Sema &S; +}; + +struct DiagNonTrivalCUnionCopyVisitor + : CopiedTypeVisitor { + using Super = CopiedTypeVisitor; + + DiagNonTrivalCUnionCopyVisitor(QualType OrigTy, SourceLocation OrigLoc, + Sema::NonTrivialCUnionContext UseContext, + Sema &S) + : OrigTy(OrigTy), OrigLoc(OrigLoc), UseContext(UseContext), S(S) {} + + void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType QT, + const FieldDecl *FD, bool InNonTrivialUnion) { + if (const auto *AT = S.Context.getAsArrayType(QT)) + return this->asDerived().visit(S.Context.getBaseElementType(AT), FD, + InNonTrivialUnion); + return Super::visitWithKind(PCK, QT, FD, InNonTrivialUnion); + } + + void visitARCStrong(QualType QT, const FieldDecl *FD, + bool InNonTrivialUnion) { + if (InNonTrivialUnion) + S.Diag(FD->getLocation(), diag::note_non_trivial_c_union) + << 1 << 2 << QT << FD->getName(); + } + + void visitARCWeak(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) { + if (InNonTrivialUnion) + S.Diag(FD->getLocation(), diag::note_non_trivial_c_union) + << 1 << 2 << QT << FD->getName(); + } + + void visitStruct(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) { + const RecordDecl *RD = QT->castAs()->getDecl(); + if (RD->isUnion()) { + if (OrigLoc.isValid()) { + bool IsUnion = false; + if (auto *OrigRD = OrigTy->getAsRecordDecl()) + IsUnion = OrigRD->isUnion(); + S.Diag(OrigLoc, diag::err_non_trivial_c_union_in_invalid_context) + << 2 << OrigTy << IsUnion << UseContext; + // Reset OrigLoc so that this diagnostic is emitted only once. + OrigLoc = SourceLocation(); + } + InNonTrivialUnion = true; + } + + if (InNonTrivialUnion) + S.Diag(RD->getLocation(), diag::note_non_trivial_c_union) + << 0 << 2 << QT.getUnqualifiedType() << ""; + + for (const FieldDecl *FD : RD->fields()) + asDerived().visit(FD->getType(), FD, InNonTrivialUnion); + } + + void preVisit(QualType::PrimitiveCopyKind PCK, QualType QT, + const FieldDecl *FD, bool InNonTrivialUnion) {} + void visitTrivial(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {} + void visitVolatileTrivial(QualType QT, const FieldDecl *FD, + bool InNonTrivialUnion) {} + + // The non-trivial C union type or the struct/union type that contains a + // non-trivial C union. + QualType OrigTy; + SourceLocation OrigLoc; + Sema::NonTrivialCUnionContext UseContext; + Sema &S; +}; + +} // namespace + +void Sema::checkNonTrivialCUnion(QualType QT, SourceLocation Loc, + NonTrivialCUnionContext UseContext, + unsigned NonTrivialKind) { + assert((QT.hasNonTrivialToPrimitiveDefaultInitializeCUnion() || + QT.hasNonTrivialToPrimitiveDestructCUnion() || + QT.hasNonTrivialToPrimitiveCopyCUnion()) && + "shouldn't be called if type doesn't have a non-trivial C union"); + + if ((NonTrivialKind & NTCUK_Init) && + QT.hasNonTrivialToPrimitiveDefaultInitializeCUnion()) + DiagNonTrivalCUnionDefaultInitializeVisitor(QT, Loc, UseContext, *this) + .visit(QT, nullptr, false); + if ((NonTrivialKind & NTCUK_Destruct) && + QT.hasNonTrivialToPrimitiveDestructCUnion()) + DiagNonTrivalCUnionDestructedTypeVisitor(QT, Loc, UseContext, *this) + .visit(QT, nullptr, false); + if ((NonTrivialKind & NTCUK_Copy) && QT.hasNonTrivialToPrimitiveCopyCUnion()) + DiagNonTrivalCUnionCopyVisitor(QT, Loc, UseContext, *this) + .visit(QT, nullptr, false); +} + /// AddInitializerToDecl - Adds the initializer Init to the /// declaration dcl. If DirectInit is true, this is C++ direct /// initialization rather than copy initialization. @@ -11317,7 +11589,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // do nothing // OpenCL v1.2 s6.5.3: __constant locals must be constant-initialized. - // This is true even in OpenCL C++. + // This is true even in C++ for OpenCL. } else if (VDecl->getType().getAddressSpace() == LangAS::opencl_constant) { CheckForConstantInitializer(Init, DclT); @@ -11475,6 +11747,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { CheckForConstantInitializer(Init, DclT); } + QualType InitType = Init->getType(); + if (!InitType.isNull() && + (InitType.hasNonTrivialToPrimitiveDefaultInitializeCUnion() || + InitType.hasNonTrivialToPrimitiveCopyCUnion())) + checkNonTrivialCUnionInInitializer(Init, Init->getExprLoc()); + // We will represent direct-initialization similarly to copy-initialization: // int x(1); -as-> int x = 1; // ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c); @@ -11599,7 +11877,14 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { return; } - switch (Var->isThisDeclarationADefinition()) { + VarDecl::DefinitionKind DefKind = Var->isThisDeclarationADefinition(); + if (!Var->isInvalidDecl() && DefKind != VarDecl::DeclarationOnly && + Var->getType().hasNonTrivialToPrimitiveDefaultInitializeCUnion()) + checkNonTrivialCUnion(Var->getType(), Var->getLocation(), + NTCUC_DefaultInitializedObject, NTCUK_Init); + + + switch (DefKind) { case VarDecl::Definition: if (!Var->isStaticDataMember() || !Var->getAnyInitializer()) break; @@ -11909,7 +12194,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { // Cache the result of checking for constant initialization. Optional CacheHasConstInit; - const Expr *CacheCulprit; + const Expr *CacheCulprit = nullptr; auto checkConstInit = [&]() mutable { if (!CacheHasConstInit) CacheHasConstInit = var->getInit()->isConstantInitializer( @@ -12692,6 +12977,11 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, Context.getAdjustedParameterType(T), TSInfo, SC, nullptr); + if (New->getType().hasNonTrivialToPrimitiveDestructCUnion() || + New->getType().hasNonTrivialToPrimitiveCopyCUnion()) + checkNonTrivialCUnion(New->getType(), New->getLocation(), + NTCUC_FunctionParam, NTCUK_Destruct|NTCUK_Copy); + // Parameters can not be abstract class types. // For record types, this is done by the AbstractClassUsageDiagnoser once // the class has been completely parsed. @@ -15938,7 +16228,6 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // Verify that all the fields are okay. SmallVector RecFields; - bool ObjCFieldLifetimeErrReported = false; for (ArrayRef::iterator i = Fields.begin(), end = Fields.end(); i != end; ++i) { FieldDecl *FD = cast(*i); @@ -16077,38 +16366,12 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, Record->setHasObjectMember(true); if (Record && FDTTy->getDecl()->hasVolatileMember()) Record->setHasVolatileMember(true); - if (Record && Record->isUnion() && - FD->getType().isNonTrivialPrimitiveCType(Context)) - Diag(FD->getLocation(), - diag::err_nontrivial_primitive_type_in_union); } else if (FDTy->isObjCObjectType()) { /// A field cannot be an Objective-c object Diag(FD->getLocation(), diag::err_statically_allocated_object) << FixItHint::CreateInsertion(FD->getLocation(), "*"); QualType T = Context.getObjCObjectPointerType(FD->getType()); FD->setType(T); - } else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && - Record && !ObjCFieldLifetimeErrReported && Record->isUnion() && - !getLangOpts().CPlusPlus) { - // It's an error in ARC or Weak if a field has lifetime. - // We don't want to report this in a system header, though, - // so we just make the field unavailable. - // FIXME: that's really not sufficient; we need to make the type - // itself invalid to, say, initialize or copy. - QualType T = FD->getType(); - if (T.hasNonTrivialObjCLifetime()) { - SourceLocation loc = FD->getLocation(); - if (getSourceManager().isInSystemHeader(loc)) { - if (!FD->hasAttr()) { - FD->addAttr(UnavailableAttr::CreateImplicit(Context, "", - UnavailableAttr::IR_ARCFieldWithOwnership, loc)); - } - } else { - Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag) - << T->isBlockPointerType() << Record->getTagKind(); - } - ObjCFieldLifetimeErrReported = true; - } } else if (getLangOpts().ObjC && getLangOpts().getGC() != LangOptions::NonGC && Record && !Record->hasObjectMember()) { @@ -16128,14 +16391,23 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, if (Record && !getLangOpts().CPlusPlus && !FD->hasAttr()) { QualType FT = FD->getType(); - if (FT.isNonTrivialToPrimitiveDefaultInitialize()) + if (FT.isNonTrivialToPrimitiveDefaultInitialize()) { Record->setNonTrivialToPrimitiveDefaultInitialize(true); + if (FT.hasNonTrivialToPrimitiveDefaultInitializeCUnion() || + Record->isUnion()) + Record->setHasNonTrivialToPrimitiveDefaultInitializeCUnion(true); + } QualType::PrimitiveCopyKind PCK = FT.isNonTrivialToPrimitiveCopy(); - if (PCK != QualType::PCK_Trivial && PCK != QualType::PCK_VolatileTrivial) + if (PCK != QualType::PCK_Trivial && PCK != QualType::PCK_VolatileTrivial) { Record->setNonTrivialToPrimitiveCopy(true); + if (FT.hasNonTrivialToPrimitiveCopyCUnion() || Record->isUnion()) + Record->setHasNonTrivialToPrimitiveCopyCUnion(true); + } if (FT.isDestructedType()) { Record->setNonTrivialToPrimitiveDestroy(true); Record->setParamDestroyedInCallee(true); + if (FT.hasNonTrivialToPrimitiveDestructCUnion() || Record->isUnion()) + Record->setHasNonTrivialToPrimitiveDestructCUnion(true); } if (const auto *RT = FT->getAs()) { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 802ca52371a58b..ee06f8ae511471 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -900,7 +900,7 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { const Expr *SizeExpr = AL.getArgAsExpr(0); int SizeArgNoVal; // Parameter indices are 1-indexed, hence Index=1 - if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNoVal, /*Index=*/1)) + if (!checkPositiveIntArgument(S, AL, SizeExpr, SizeArgNoVal, /*Idx=*/1)) return; if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/0)) return; @@ -911,7 +911,7 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { const Expr *NumberExpr = AL.getArgAsExpr(1); int Val; // Parameter indices are 1-based, hence Index=2 - if (!checkPositiveIntArgument(S, AL, NumberExpr, Val, /*Index=*/2)) + if (!checkPositiveIntArgument(S, AL, NumberExpr, Val, /*Idx=*/2)) return; if (!checkParamIsIntegerType(S, FD, AL, /*AttrArgNo=*/1)) return; @@ -1673,7 +1673,7 @@ void Sema::AddAllocAlignAttr(SourceRange AttrRange, Decl *D, Expr *ParamExpr, ParamIdx Idx; const auto *FuncDecl = cast(D); if (!checkFunctionOrMethodParameterIndex(*this, FuncDecl, TmpAttr, - /*AttrArgNo=*/1, ParamExpr, Idx)) + /*AttrArgNum=*/1, ParamExpr, Idx)) return; QualType Ty = getFunctionOrMethodParamType(D, Idx.getASTIndex()); @@ -4669,7 +4669,7 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, break; case TargetInfo::CCCR_Warning: { - Diag(Attrs.getLoc(), diag::warn_cconv_ignored) + Diag(Attrs.getLoc(), diag::warn_cconv_unsupported) << Attrs << (int)CallingConventionIgnoredReason::ForThisTarget; // This convention is not valid for the target. Use the default function or diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index b23352bffbf179..dd77fc55721fb7 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -11168,8 +11168,8 @@ Sema::findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create( Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo, - BaseCtor->getExplicitSpecifier(), /*Inline=*/true, - /*ImplicitlyDeclared=*/true, + BaseCtor->getExplicitSpecifier(), /*isInline=*/true, + /*isImplicitlyDeclared=*/true, Constexpr ? BaseCtor->getConstexprKind() : CSK_unspecified, InheritedConstructor(Shadow, BaseCtor)); if (Shadow->isInvalidDecl()) @@ -11190,7 +11190,7 @@ Sema::findInheritingConstructor(SourceLocation Loc, Context.getTrivialTypeSourceInfo(FPT->getParamType(I), UsingLoc); ParmVarDecl *PD = ParmVarDecl::Create( Context, DerivedCtor, UsingLoc, UsingLoc, /*IdentifierInfo=*/nullptr, - FPT->getParamType(I), TInfo, SC_None, /*DefaultArg=*/nullptr); + FPT->getParamType(I), TInfo, SC_None, /*DefArg=*/nullptr); PD->setScopeInfo(0, I); PD->setImplicit(); // Ensure attributes are propagated onto parameters (this matters for @@ -11751,7 +11751,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, // Create the reference to operator=. ExprResult OpEqualRef - = S.BuildMemberReferenceExpr(To.build(S, Loc), T, Loc, /*isArrow=*/false, + = S.BuildMemberReferenceExpr(To.build(S, Loc), T, Loc, /*IsArrow=*/false, SS, /*TemplateKWLoc=*/SourceLocation(), /*FirstQualifierInScope=*/nullptr, OpLookup, @@ -13272,7 +13272,7 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, diag::err_operator_new_delete_dependent_result_type) << FnDecl->getDeclName() << ExpectedResultType; - // OpenCL C++: the operator is valid on any address space. + // The operator is valid on any address space for OpenCL. if (SemaRef.getLangOpts().OpenCLCPlusPlus) { if (auto *PtrTy = ResultType->getAs()) { ResultType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy); @@ -13305,7 +13305,7 @@ CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, // Check that the first parameter type is what we expect. if (SemaRef.getLangOpts().OpenCLCPlusPlus) { - // OpenCL C++: the operator is valid on any address space. + // The operator is valid on any address space for OpenCL. if (auto *PtrTy = FnDecl->getParamDecl(0)->getType()->getAs()) { FirstParamType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy); diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 21d9b8c32266d3..e629837eb71d19 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -1587,7 +1587,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // add the '*'. if (type->getAs()) { SourceLocation starLoc = getLocForEndOfToken(loc); - D.AddTypeInfo(DeclaratorChunk::getPointer(/*typeQuals=*/0, starLoc, + D.AddTypeInfo(DeclaratorChunk::getPointer(/*TypeQuals=*/0, starLoc, SourceLocation(), SourceLocation(), SourceLocation(), diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 746d3e7e119016..d8869ffe945a23 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1083,8 +1083,8 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS, LHSType = S.Context.FloatTy; return handleIntToFloatConversion(S, LHS, RHS, LHSType, RHSType, - /*convertFloat=*/!IsCompAssign, - /*convertInt=*/ true); + /*ConvertFloat=*/!IsCompAssign, + /*ConvertInt=*/ true); } assert(RHSFloat); return handleIntToFloatConversion(S, RHS, LHS, RHSType, LHSType, @@ -2151,7 +2151,7 @@ recoverFromMSUnqualifiedLookup(Sema &S, ASTContext &Context, return CXXDependentScopeMemberExpr::Create( Context, /*This=*/nullptr, ThisType, /*IsArrow=*/true, /*Op=*/SourceLocation(), NestedNameSpecifierLoc(), TemplateKWLoc, - /*FirstQualifierInScope=*/nullptr, NameInfo, TemplateArgs); + /*FirstQualifierFoundInScope=*/nullptr, NameInfo, TemplateArgs); } // Synthesize a fake NNS that points to the derived class. This will @@ -6066,7 +6066,7 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, ILE->setInit(i, ConstantExpr::Create(Context, Init)); } - Expr *E = new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType, + auto *E = new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType, VK, LiteralExpr, isFileScope); if (isFileScope) { if (!LiteralExpr->isTypeDependent() && @@ -6084,6 +6084,19 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, return ExprError(); } + // Compound literals that have automatic storage duration are destroyed at + // the end of the scope. Emit diagnostics if it is or contains a C union type + // that is non-trivial to destruct. + if (!isFileScope) + if (E->getType().hasNonTrivialToPrimitiveDestructCUnion()) + checkNonTrivialCUnion(E->getType(), E->getExprLoc(), + NTCUC_CompoundLiteral, NTCUK_Destruct); + + if (E->getType().hasNonTrivialToPrimitiveDefaultInitializeCUnion() || + E->getType().hasNonTrivialToPrimitiveCopyCUnion()) + checkNonTrivialCUnionInInitializer(E->getInitializer(), + E->getInitializer()->getExprLoc()); + return MaybeBindToTemporary(E); } @@ -7295,10 +7308,10 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, // GCC compatibility: soften pointer/integer mismatch. Note that // null pointers have been filtered out by this point. if (checkPointerIntegerMismatch(*this, LHS, RHS.get(), QuestionLoc, - /*isIntFirstExpr=*/true)) + /*IsIntFirstExpr=*/true)) return RHSTy; if (checkPointerIntegerMismatch(*this, RHS, LHS.get(), QuestionLoc, - /*isIntFirstExpr=*/false)) + /*IsIntFirstExpr=*/false)) return LHSTy; // Emit a better diagnostic if one of the expressions is a null pointer @@ -9092,7 +9105,7 @@ static void DiagnoseBadDivideOrRemainderValues(Sema& S, ExprResult &LHS, QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign, bool IsDiv) { - checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); + checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false); if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType()) @@ -9116,7 +9129,7 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS, QualType Sema::CheckRemainderOperands( ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign) { - checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); + checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false); if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType()) { @@ -9405,7 +9418,7 @@ static void diagnosePointerIncompatibility(Sema &S, SourceLocation Loc, QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, BinaryOperatorKind Opc, QualType* CompLHSTy) { - checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); + checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false); if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType()) { @@ -9499,7 +9512,7 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS, QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, QualType* CompLHSTy) { - checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); + checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false); if (LHS.get()->getType()->isVectorType() || RHS.get()->getType()->isVectorType()) { @@ -9787,7 +9800,7 @@ static QualType checkVectorShift(Sema &S, ExprResult &LHS, ExprResult &RHS, QualType Sema::CheckShiftOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, BinaryOperatorKind Opc, bool IsCompAssign) { - checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); + checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false); // Vector shifts promote their scalar inputs to vector type. if (LHS.get()->getType()->isVectorType() || @@ -9956,7 +9969,7 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) { Selector IsEqualSel = S.NSAPIObj->getIsEqualSelector(); ObjCMethodDecl *Method = S.LookupMethodInObjectType(IsEqualSel, InterfaceType, - /*instance=*/true); + /*IsInstance=*/true); if (!Method) { if (Type->isObjCIdType()) { // For 'id', just check the global pool. @@ -9965,7 +9978,7 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) { } else { // Check protocols. Method = S.LookupMethodInQualifiedType(IsEqualSel, Type, - /*instance=*/true); + /*IsInstance=*/true); } } @@ -10465,7 +10478,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, return QualType(); } - checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/true); + checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/true); // Handle vector comparisons separately. if (LHS.get()->getType()->isVectorType() || @@ -10975,7 +10988,7 @@ QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS, inline QualType Sema::CheckBitwiseOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, BinaryOperatorKind Opc) { - checkArithmeticNull(*this, LHS, RHS, Loc, /*isCompare=*/false); + checkArithmeticNull(*this, LHS, RHS, Loc, /*IsCompare=*/false); bool IsCompAssign = Opc == BO_AndAssign || Opc == BO_OrAssign || Opc == BO_XorAssign; @@ -12533,6 +12546,10 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, if (auto *VD = dyn_cast(DRE->getDecl())) if (VD->hasLocalStorage() && getCurScope()->isDeclScope(VD)) BE->getBlockDecl()->setCanAvoidCopyToHeap(); + + if (LHS.get()->getType().hasNonTrivialToPrimitiveCopyCUnion()) + checkNonTrivialCUnion(LHS.get()->getType(), LHS.get()->getExprLoc(), + NTCUC_Assignment, NTCUK_Copy); } RecordModifiableNonNullParam(*this, LHS.get()); break; @@ -13945,6 +13962,11 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, !BD->isDependentContext()) computeNRVO(Body, BSI); + if (RetTy.hasNonTrivialToPrimitiveDestructCUnion() || + RetTy.hasNonTrivialToPrimitiveCopyCUnion()) + checkNonTrivialCUnion(RetTy, BD->getCaretLocation(), NTCUC_FunctionReturn, + NTCUK_Destruct|NTCUK_Copy); + PopDeclContext(); // Pop the block scope now but keep it alive to the end of this function. @@ -15604,7 +15626,7 @@ static bool captureInLambda(LambdaScopeInfo *LSI, // Add the capture. if (BuildAndDiagnose) - LSI->addCapture(Var, /*IsBlock=*/false, ByRef, RefersToCapturedVariable, + LSI->addCapture(Var, /*isBlock=*/false, ByRef, RefersToCapturedVariable, Loc, EllipsisLoc, CaptureType, Invalid); return !Invalid; @@ -16196,6 +16218,15 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E, } ExprResult Sema::CheckLValueToRValueConversionOperand(Expr *E) { + // Check whether the operand is or contains an object of non-trivial C union + // type. + if (E->getType().isVolatileQualified() && + (E->getType().hasNonTrivialToPrimitiveDestructCUnion() || + E->getType().hasNonTrivialToPrimitiveCopyCUnion())) + checkNonTrivialCUnion(E->getType(), E->getExprLoc(), + Sema::NTCUC_LValueToRValueVolatile, + NTCUK_Destruct|NTCUK_Copy); + // C++2a [basic.def.odr]p4: // [...] an expression of non-volatile-qualified non-class type to which // the lvalue-to-rvalue conversion is applied [...] diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 3029861f2303ae..705e3b9bd7fb90 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -529,7 +529,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, ExprResult Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, bool isType, void *TyOrExpr, SourceLocation RParenLoc) { - // OpenCL C++ 1.0 s2.9: typeid is not supported. + // typeid is not supported in OpenCL. if (getLangOpts().OpenCLCPlusPlus) { return ExprError(Diag(OpLoc, diag::err_openclcxx_not_supported) << "typeid"); @@ -1254,7 +1254,7 @@ ExprResult Sema::ActOnCXXThis(SourceLocation Loc) { QualType ThisTy = getCurrentThisType(); if (ThisTy.isNull()) return Diag(Loc, diag::err_invalid_this_use); - return BuildCXXThisExpr(Loc, ThisTy, /*isImplicit=*/false); + return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false); } Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type, @@ -2656,8 +2656,8 @@ void Sema::DeclareGlobalNewDelete() { if (GlobalNewDeleteDeclared) return; - // OpenCL C++ 1.0 s2.9: the implicitly declared new and delete operators - // are not supported. + // The implicitly declared new and delete operators + // are not supported in OpenCL. if (getLangOpts().OpenCLCPlusPlus) return; @@ -4216,17 +4216,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, break; case ICK_Block_Pointer_Conversion: { - QualType LHSType = Context.getCanonicalType(ToType).getUnqualifiedType(); - QualType RHSType = Context.getCanonicalType(FromType).getUnqualifiedType(); - - // Assumptions based on Sema::IsBlockPointerConversion. - assert(isa(LHSType) && "BlockPointerType expected"); - assert(isa(RHSType) && "BlockPointerType expected"); - LangAS AddrSpaceL = - LHSType->getAs()->getPointeeType().getAddressSpace(); + ToType->castAs()->getPointeeType().getAddressSpace(); LangAS AddrSpaceR = - RHSType->getAs()->getPointeeType().getAddressSpace(); + FromType->castAs()->getPointeeType().getAddressSpace(); + assert(Qualifiers::isAddressSpaceSupersetOf(AddrSpaceL, AddrSpaceR) && + "Invalid cast"); CastKind Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast; From = ImpCastExprToType(From, ToType.getUnqualifiedType(), Kind, diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 2431f96fb3f754..c856e37e99e7a0 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1106,7 +1106,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, SourceLocation Loc = R.getNameLoc(); if (SS.getRange().isValid()) Loc = SS.getRange().getBegin(); - BaseExpr = BuildCXXThisExpr(Loc, BaseExprType, /*isImplicit=*/true); + BaseExpr = BuildCXXThisExpr(Loc, BaseExprType, /*IsImplicit=*/true); } // Check the use of this member. @@ -1130,7 +1130,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, if (VarDecl *Var = dyn_cast(MemberDecl)) { return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, - FoundDecl, /*MultipleCandidates=*/false, + FoundDecl, /*HadMultipleCandidates=*/false, MemberNameInfo, Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary); } @@ -1147,14 +1147,14 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, } return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, - MemberFn, FoundDecl, /*MultipleCandidates=*/false, + MemberFn, FoundDecl, /*HadMultipleCandidates=*/false, MemberNameInfo, type, valueKind, OK_Ordinary); } assert(!isa(MemberDecl) && "member function not C++ method?"); if (EnumConstantDecl *Enum = dyn_cast(MemberDecl)) { return BuildMemberExpr(BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Enum, - FoundDecl, /*MultipleCandidates=*/false, + FoundDecl, /*HadMultipleCandidates=*/false, MemberNameInfo, Enum->getType(), VK_RValue, OK_Ordinary); } @@ -1163,7 +1163,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, *this, VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc)) return BuildMemberExpr( BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, FoundDecl, - /*MultipleCandidates=*/false, MemberNameInfo, + /*HadMultipleCandidates=*/false, MemberNameInfo, Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary); return ExprError(); } @@ -1822,7 +1822,7 @@ Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, return BuildMemberExpr(Base.get(), IsArrow, OpLoc, &SS, /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl, - /*MultipleCandidates=*/false, MemberNameInfo, + /*HadMultipleCandidates=*/false, MemberNameInfo, MemberType, VK, OK); } @@ -1851,7 +1851,7 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation Loc = R.getNameLoc(); if (SS.getRange().isValid()) Loc = SS.getRange().getBegin(); - baseExpr = BuildCXXThisExpr(loc, ThisTy, /*isImplicit=*/true); + baseExpr = BuildCXXThisExpr(loc, ThisTy, /*IsImplicit=*/true); } return BuildMemberReferenceExpr(baseExpr, ThisTy, diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index d2a4a0979d15a5..bc1069609336ce 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3931,7 +3931,7 @@ static void TryConstructorInitialization(Sema &S, Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, CandidateSet, DestType, Ctors, Best, CopyInitialization, AllowExplicit, - /*OnlyListConstructor=*/true, + /*OnlyListConstructors=*/true, IsListInit); } @@ -4118,7 +4118,7 @@ static void TryReferenceListInitialization(Sema &S, if (Sequence) { if (DestType->isRValueReferenceType() || (T1Quals.hasConst() && !T1Quals.hasVolatile())) - Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true); + Sequence.AddReferenceBindingStep(cv1T1, /*BindingTemporary=*/true); else Sequence.SetFailed( InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary); @@ -4833,7 +4833,7 @@ static void TryReferenceInitializationCore(Sema &S, return; } - Sequence.AddReferenceBindingStep(cv1T1IgnoreAS, /*bindingTemporary=*/true); + Sequence.AddReferenceBindingStep(cv1T1IgnoreAS, /*BindingTemporary=*/true); if (T1Quals.hasAddressSpace()) { if (!Qualifiers::isAddressSpaceSupersetOf(T1Quals.getAddressSpace(), @@ -5640,6 +5640,9 @@ void InitializationSequence::InitializeFrom(Sema &S, bool allowObjCWritebackConversion = S.getLangOpts().ObjCAutoRefCount && Entity.isParameterKind(); + if (TryOCLSamplerInitialization(S, *this, DestType, Initializer)) + return; + // We're at the end of the line for C: it's either a write-back conversion // or it's a C assignment. There's no need to check anything else. if (!S.getLangOpts().CPlusPlus) { @@ -5649,9 +5652,6 @@ void InitializationSequence::InitializeFrom(Sema &S, return; } - if (TryOCLSamplerInitialization(S, *this, DestType, Initializer)) - return; - if (TryOCLZeroOpaqueTypeInitialization(S, *this, DestType, Initializer)) return; diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 268e15c20ef3e4..986524e6d56b4e 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1328,7 +1328,7 @@ static void addFunctionPointerConversion(Sema &S, S.Context.getTranslationUnitDecl(), From->getBeginLoc(), From->getLocation(), From->getIdentifier(), From->getType(), From->getTypeSourceInfo(), From->getStorageClass(), - /*DefaultArg=*/nullptr)); + /*DefArg=*/nullptr)); CallOpConvTL.setParam(I, From); CallOpConvNameTL.setParam(I, From); } @@ -1376,7 +1376,7 @@ static void addFunctionPointerConversion(Sema &S, CXXMethodDecl *Invoke = CXXMethodDecl::Create( S.Context, Class, Loc, DeclarationNameInfo(InvokerName, Loc), InvokerFunctionTy, CallOperator->getTypeSourceInfo(), SC_Static, - /*IsInline=*/true, CSK_unspecified, CallOperator->getBody()->getEndLoc()); + /*isInline=*/true, CSK_unspecified, CallOperator->getBody()->getEndLoc()); for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) InvokerParams[I]->setOwningFunction(Invoke); Invoke->setParams(InvokerParams); @@ -1860,7 +1860,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, Context, Block, From->getBeginLoc(), From->getLocation(), From->getIdentifier(), From->getType(), From->getTypeSourceInfo(), From->getStorageClass(), - /*DefaultArg=*/nullptr)); + /*DefArg=*/nullptr)); } Block->setParams(BlockParams); @@ -1875,8 +1875,8 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, ConvLocation, nullptr, Src->getType(), CapVarTSI, SC_None); - BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false, - /*Nested=*/false, /*Copy=*/Init.get()); + BlockDecl::Capture Capture(/*variable=*/CapVar, /*byRef=*/false, + /*nested=*/false, /*copy=*/Init.get()); Block->setCaptures(Context, Capture, /*CapturesCXXThis=*/false); // Add a fake function body to the block. IR generation is responsible diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index c0b946a98d1dce..8a24dd884a76ab 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -688,7 +688,7 @@ static void InsertOCLBuiltinDeclarations(Sema &S, LookupResult &LR, unsigned Len) { for (unsigned i = 0; i < Len; ++i) { - OpenCLBuiltinDecl &Decl = OpenCLBuiltins[Index - 1 + i]; + const OpenCLBuiltinDecl &Decl = OpenCLBuiltins[Index - 1 + i]; ASTContext &Context = S.Context; // Ignore this BIF if the version is incorrect. diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index 68c2286cf492e3..10de0ca91221ce 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -206,7 +206,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc, PP.getIdentifierInfo(ModuleName), Path[0].second); Mod = getModuleLoader().loadModule(ModuleLoc, {ModuleNameLoc}, Module::AllVisible, - /*IsIncludeDirective=*/false); + /*IsInclusionDirective=*/false); if (!Mod) { Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName; // Create an empty module interface unit for error recovery. @@ -323,7 +323,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc, Module *Mod = getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible, - /*IsIncludeDirective=*/false); + /*IsInclusionDirective=*/false); if (!Mod) return true; diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 2521441f8bc713..e5c014501431ba 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -1288,7 +1288,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, PropertyIvarLoc,PropertyIvarLoc, PropertyIvar, - PropertyIvarType, /*Dinfo=*/nullptr, + PropertyIvarType, /*TInfo=*/nullptr, ObjCIvarDecl::Private, (Expr *)nullptr, true); if (RequireNonAbstractType(PropertyIvarLoc, diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index b669929e655f3e..bd68011c18b231 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -4992,7 +4992,8 @@ class LoopCounterRefChecker final bool VisitMemberExpr(const MemberExpr *E) { if (isa(E->getBase()->IgnoreParens())) { const ValueDecl *VD = E->getMemberDecl(); - return checkDecl(E, VD); + if (isa(VD) || isa(VD)) + return checkDecl(E, VD); } return false; } @@ -6000,7 +6001,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) { NestedLoopCount = Result.Val.getInt().getLimitedValue(); } else { - Built.clear(/*size=*/1); + Built.clear(/*Size=*/1); return 1; } } @@ -6022,7 +6023,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, } OrderedLoopCount = Result.getLimitedValue(); } else { - Built.clear(/*size=*/1); + Built.clear(/*Size=*/1); return 1; } } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 11595fac2cb6bd..d8c4ea48ebce70 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1851,6 +1851,10 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, (From->EvaluateKnownConstInt(S.getASTContext()) == 0)) { SCS.Second = ICK_Zero_Queue_Conversion; FromType = ToType; + } else if (ToType->isSamplerT() && + From->isIntegerConstantExpr(S.getASTContext())) { + SCS.Second = ICK_Compatible_Conversion; + FromType = ToType; } else { // No second conversion required. SCS.Second = ICK_Identity; @@ -1950,7 +1954,7 @@ IsTransparentUnionStandardConversion(Sema &S, Expr* From, // It's compatible if the expression matches any of the fields. for (const auto *it : UD->fields()) { if (IsStandardConversion(S, From, it->getType(), InOverloadResolution, SCS, - CStyle, /*ObjCWritebackConversion=*/false)) { + CStyle, /*AllowObjCWritebackConversion=*/false)) { ToType = it->getType(); return true; } @@ -5423,7 +5427,7 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, : TryCopyInitialization(S, From, T, /*SuppressUserConversions=*/false, /*InOverloadResolution=*/false, - /*AllowObjcWritebackConversion=*/false, + /*AllowObjCWritebackConversion=*/false, /*AllowExplicit=*/false); StandardConversionSequence *SCS = nullptr; switch (ICS.getKind()) { @@ -7319,7 +7323,7 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, ++Oper) AddMethodCandidate(Oper.getPair(), Args[0]->getType(), Args[0]->Classify(Context), Args.slice(1), - CandidateSet, /*SuppressUserConversions=*/false); + CandidateSet, /*SuppressUserConversion=*/false); } } @@ -8420,7 +8424,7 @@ class BuiltinOperatorOverloadBuilder { isEqualOp ? *Ptr : S.Context.getPointerDiffType(), }; S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, - /*IsAssigmentOperator=*/ isEqualOp); + /*IsAssignmentOperator=*/ isEqualOp); bool NeedVolatile = !(*Ptr).isVolatileQualified() && VisibleTypeConversionsQuals.hasVolatile(); @@ -8429,7 +8433,7 @@ class BuiltinOperatorOverloadBuilder { ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, - /*IsAssigmentOperator=*/isEqualOp); + /*IsAssignmentOperator=*/isEqualOp); } if (!(*Ptr).isRestrictQualified() && @@ -8438,7 +8442,7 @@ class BuiltinOperatorOverloadBuilder { ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr)); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, - /*IsAssigmentOperator=*/isEqualOp); + /*IsAssignmentOperator=*/isEqualOp); if (NeedVolatile) { // volatile restrict version @@ -8448,7 +8452,7 @@ class BuiltinOperatorOverloadBuilder { (Qualifiers::Volatile | Qualifiers::Restrict))); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, - /*IsAssigmentOperator=*/isEqualOp); + /*IsAssignmentOperator=*/isEqualOp); } } } @@ -8469,7 +8473,7 @@ class BuiltinOperatorOverloadBuilder { // non-volatile version S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, - /*IsAssigmentOperator=*/true); + /*IsAssignmentOperator=*/true); bool NeedVolatile = !(*Ptr).isVolatileQualified() && VisibleTypeConversionsQuals.hasVolatile(); @@ -8478,7 +8482,7 @@ class BuiltinOperatorOverloadBuilder { ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, - /*IsAssigmentOperator=*/true); + /*IsAssignmentOperator=*/true); } if (!(*Ptr).isRestrictQualified() && @@ -8487,7 +8491,7 @@ class BuiltinOperatorOverloadBuilder { ParamTypes[0] = S.Context.getLValueReferenceType(S.Context.getRestrictType(*Ptr)); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, - /*IsAssigmentOperator=*/true); + /*IsAssignmentOperator=*/true); if (NeedVolatile) { // volatile restrict version @@ -8497,7 +8501,7 @@ class BuiltinOperatorOverloadBuilder { (Qualifiers::Volatile | Qualifiers::Restrict))); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, - /*IsAssigmentOperator=*/true); + /*IsAssignmentOperator=*/true); } } } @@ -8530,14 +8534,14 @@ class BuiltinOperatorOverloadBuilder { // Add this built-in operator as a candidate (VQ is empty). ParamTypes[0] = S.Context.getLValueReferenceType(LeftBaseTy); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, - /*IsAssigmentOperator=*/isEqualOp); + /*IsAssignmentOperator=*/isEqualOp); // Add this built-in operator as a candidate (VQ is 'volatile'). if (VisibleTypeConversionsQuals.hasVolatile()) { ParamTypes[0] = S.Context.getVolatileType(LeftBaseTy); ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, - /*IsAssigmentOperator=*/isEqualOp); + /*IsAssignmentOperator=*/isEqualOp); } } } @@ -8556,14 +8560,14 @@ class BuiltinOperatorOverloadBuilder { // Add this built-in operator as a candidate (VQ is empty). ParamTypes[0] = S.Context.getLValueReferenceType(*Vec1); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, - /*IsAssigmentOperator=*/isEqualOp); + /*IsAssignmentOperator=*/isEqualOp); // Add this built-in operator as a candidate (VQ is 'volatile'). if (VisibleTypeConversionsQuals.hasVolatile()) { ParamTypes[0] = S.Context.getVolatileType(*Vec1); ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, - /*IsAssigmentOperator=*/isEqualOp); + /*IsAssignmentOperator=*/isEqualOp); } } } @@ -9012,7 +9016,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, continue; AddOverloadCandidate(FD, FoundDecl, Args, CandidateSet, - /*SupressUserConversions=*/false, PartialOverloading, + /*SuppressUserConversions=*/false, PartialOverloading, /*AllowExplicit*/ true, /*AllowExplicitConversions*/ false, ADLCallKind::UsesADL); @@ -11763,7 +11767,7 @@ static void AddOverloadedCallCandidate(Sema &S, return; S.AddOverloadCandidate(Func, FoundDecl, Args, CandidateSet, - /*SuppressUsedConversions=*/false, + /*SuppressUserConversions=*/false, PartialOverloading); return; } @@ -11772,7 +11776,7 @@ static void AddOverloadedCallCandidate(Sema &S, = dyn_cast(Callee)) { S.AddTemplateOverloadCandidate(FuncTemplate, FoundDecl, ExplicitTemplateArgs, Args, CandidateSet, - /*SuppressUsedConversions=*/false, + /*SuppressUserConversions=*/false, PartialOverloading); return; } @@ -13066,7 +13070,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, AddMethodTemplateCandidate( cast(Func), I.getPair(), ActingDC, TemplateArgs, ObjectType, ObjectClassification, Args, CandidateSet, - /*SuppressUsedConversions=*/false); + /*SuppressUserConversions=*/false); } } @@ -13262,7 +13266,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, Oper != OperEnd; ++Oper) { AddMethodCandidate(Oper.getPair(), Object.get()->getType(), Object.get()->Classify(Context), Args, CandidateSet, - /*SuppressUserConversions=*/false); + /*SuppressUserConversion=*/false); } // C++ [over.call.object]p2: @@ -13537,7 +13541,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); Oper != OperEnd; ++Oper) { AddMethodCandidate(Oper.getPair(), Base->getType(), Base->Classify(Context), - None, CandidateSet, /*SuppressUserConversions=*/false); + None, CandidateSet, /*SuppressUserConversion=*/false); } bool HadMultipleCandidates = (CandidateSet.size() > 1); @@ -13919,7 +13923,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, if (MemExpr->getQualifier()) Loc = MemExpr->getQualifierLoc().getBeginLoc(); Base = - BuildCXXThisExpr(Loc, MemExpr->getBaseType(), /*isImplicit=*/true); + BuildCXXThisExpr(Loc, MemExpr->getBaseType(), /*IsImplicit=*/true); } } else Base = MemExpr->getBase(); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 0e5881e327a8b0..480155df899018 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -2447,7 +2447,7 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, ExprResult SizeOfVLAExprR = ActOnUnaryExprOrTypeTraitExpr( EndVar->getLocation(), UETT_SizeOf, - /*isType=*/true, + /*IsType=*/true, CreateParsedType(VAT->desugar(), Context.getTrivialTypeSourceInfo( VAT->desugar(), RangeLoc)) .getAsOpaquePtr(), @@ -2457,7 +2457,7 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, ExprResult SizeOfEachElementExprR = ActOnUnaryExprOrTypeTraitExpr( EndVar->getLocation(), UETT_SizeOf, - /*isType=*/true, + /*IsType=*/true, CreateParsedType(VAT->desugar(), Context.getTrivialTypeSourceInfo( VAT->getElementType(), RangeLoc)) diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index ec8958c3c5f90a..b123a739a7ab1e 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -849,7 +849,7 @@ Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member, return CXXDependentScopeMemberExpr::Create( Context, E, T, /*IsArrow=*/false, AsmLoc, NestedNameSpecifierLoc(), SourceLocation(), - /*FirstQualifierInScope=*/nullptr, NameInfo, /*TemplateArgs=*/nullptr); + /*FirstQualifierFoundInScope=*/nullptr, NameInfo, /*TemplateArgs=*/nullptr); } const RecordType *RT = T->getAs(); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index fba8cd4eee063a..3212281cc34d2d 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -8428,8 +8428,8 @@ bool Sema::CheckFunctionTemplateSpecialization( // here that have a different target. if (LangOpts.CUDA && IdentifyCUDATarget(Specialization, - /* IgnoreImplicitHDAttributes = */ true) != - IdentifyCUDATarget(FD, /* IgnoreImplicitHDAttributes = */ true)) { + /* IgnoreImplicitHDAttr = */ true) != + IdentifyCUDATarget(FD, /* IgnoreImplicitHDAttr = */ true)) { FailedCandidates.addCandidate().set( I.getPair(), FunTmpl->getTemplatedDecl(), MakeDeductionFailureInfo(Context, TDK_CUDATargetMismatch, Info)); @@ -9587,7 +9587,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // have a different target. if (LangOpts.CUDA && IdentifyCUDATarget(Specialization, - /* IgnoreImplicitHDAttributes = */ true) != + /* IgnoreImplicitHDAttr = */ true) != IdentifyCUDATarget(D.getDeclSpec().getAttributes())) { FailedCandidates.addCandidate().set( P.getPair(), FunTmpl->getTemplatedDecl(), diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 263bc3104efe8f..b55a232d26c22e 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2872,7 +2872,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, return Sema::TDK_SubstitutionFailure; return ::FinishTemplateArgumentDeduction( - *this, Partial, /*PartialOrdering=*/false, TemplateArgs, Deduced, Info); + *this, Partial, /*IsPartialOrdering=*/false, TemplateArgs, Deduced, Info); } /// Perform template argument deduction to determine whether @@ -2913,7 +2913,7 @@ Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial, return Sema::TDK_SubstitutionFailure; return ::FinishTemplateArgumentDeduction( - *this, Partial, /*PartialOrdering=*/false, TemplateArgs, Deduced, Info); + *this, Partial, /*IsPartialOrdering=*/false, TemplateArgs, Deduced, Info); } /// Determine whether the given type T is a simple-template-id type. @@ -5067,7 +5067,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2, Info); auto *TST1 = T1->castAs(); if (FinishTemplateArgumentDeduction( - S, P2, /*PartialOrdering=*/true, + S, P2, /*IsPartialOrdering=*/true, TemplateArgumentList(TemplateArgumentList::OnStack, TST1->template_arguments()), Deduced, Info)) diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 9b23624a9a81f7..d97626551a41f7 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -619,6 +619,7 @@ ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc, if (!Pattern->containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) << Pattern->getSourceRange(); + CorrectDelayedTyposInExpr(Pattern); return ExprError(); } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 88b544068a802b..29acf6177eb9c7 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -751,7 +751,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, /*IsAmbiguous=*/false, /*LParenLoc=*/NoLoc, /*ArgInfo=*/nullptr, - /*NumArgs=*/0, + /*NumParams=*/0, /*EllipsisLoc=*/NoLoc, /*RParenLoc=*/NoLoc, /*RefQualifierIsLvalueRef=*/true, @@ -2456,6 +2456,11 @@ bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) { return true; } + if (T.hasNonTrivialToPrimitiveDestructCUnion() || + T.hasNonTrivialToPrimitiveCopyCUnion()) + checkNonTrivialCUnion(T, Loc, NTCUC_FunctionReturn, + NTCUK_Destruct|NTCUK_Copy); + return false; } @@ -7033,7 +7038,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, // stdcall and fastcall are ignored with a warning for GCC and MS // compatibility. if (CC == CC_X86StdCall || CC == CC_X86FastCall) - return S.Diag(attr.getLoc(), diag::warn_cconv_ignored) + return S.Diag(attr.getLoc(), diag::warn_cconv_unsupported) << FunctionType::getNameForCallConv(CC) << (int)Sema::CallingConventionIgnoredReason::VariadicFunction; @@ -7098,7 +7103,7 @@ void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor, // Issue a warning on ignored calling convention -- except of __stdcall. // Again, this is what MS compiler does. if (CurCC != CC_X86StdCall) - Diag(Loc, diag::warn_cconv_ignored) + Diag(Loc, diag::warn_cconv_unsupported) << FunctionType::getNameForCallConv(CurCC) << (int)Sema::CallingConventionIgnoredReason::ConstructorDestructor; // Default adjustment. @@ -7414,7 +7419,9 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State, (T->isVoidType() && !IsPointee) || // Do not deduce addr spaces for dependent types because they might end // up instantiating to a type with an explicit address space qualifier. - T->isDependentType() || + // Except for pointer or reference types because the addr space in + // template argument can only belong to a pointee. + (T->isDependentType() && !T->isPointerType() && !T->isReferenceType()) || // Do not deduce addr space of decltype because it will be taken from // its argument. T->isDecltypeType() || diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index a6122c933848b0..8df18b5c27844b 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4536,6 +4536,14 @@ QualType TreeTransform::TransformDecayedType(TypeLocBuilder &TLB, return Result; } +/// Helper to deduce addr space of a pointee type in OpenCL mode. +/// If the type is updated it will be overwritten in PointeeType param. +static void deduceOpenCLPointeeAddrSpace(Sema &SemaRef, QualType &PointeeType) { + if (PointeeType.getAddressSpace() == LangAS::Default) + PointeeType = SemaRef.Context.getAddrSpaceQualType(PointeeType, + LangAS::opencl_generic); +} + template QualType TreeTransform::TransformPointerType(TypeLocBuilder &TLB, PointerTypeLoc TL) { @@ -4544,6 +4552,9 @@ QualType TreeTransform::TransformPointerType(TypeLocBuilder &TLB, if (PointeeType.isNull()) return QualType(); + if (SemaRef.getLangOpts().OpenCL) + deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType); + QualType Result = TL.getType(); if (PointeeType->getAs()) { // A dependent pointer type 'T *' has is being transformed such @@ -4582,6 +4593,9 @@ TreeTransform::TransformBlockPointerType(TypeLocBuilder &TLB, if (PointeeType.isNull()) return QualType(); + if (SemaRef.getLangOpts().OpenCL) + deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType); + QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || PointeeType != TL.getPointeeLoc().getType()) { @@ -4611,6 +4625,9 @@ TreeTransform::TransformReferenceType(TypeLocBuilder &TLB, if (PointeeType.isNull()) return QualType(); + if (SemaRef.getLangOpts().OpenCL) + deduceOpenCLPointeeAddrSpace(SemaRef, PointeeType); + QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || PointeeType != T->getPointeeTypeAsWritten()) { @@ -5375,13 +5392,6 @@ QualType TreeTransform::TransformFunctionProtoType( if (ResultType.isNull()) return QualType(); - // Return type can not be qualified with an address space. - if (ResultType.getAddressSpace() != LangAS::Default) { - SemaRef.Diag(TL.getReturnLoc().getBeginLoc(), - diag::err_attribute_address_function_type); - return QualType(); - } - if (getDerived().TransformFunctionTypeParams( TL.getBeginLoc(), TL.getParams(), TL.getTypePtr()->param_type_begin(), diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index c3f3a370efc21e..7f2c7f09e8a3e3 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -8252,7 +8252,7 @@ void ASTReader::UpdateSema() { // Update the state of pragmas. Use the same API as if we had encountered the // pragma in the source. if(OptimizeOffPragmaLocation.isValid()) - SemaObj->ActOnPragmaOptimize(/* IsOn = */ false, OptimizeOffPragmaLocation); + SemaObj->ActOnPragmaOptimize(/* On = */ false, OptimizeOffPragmaLocation); if (PragmaMSStructState != -1) SemaObj->ActOnPragmaMSStruct((PragmaMSStructKind)PragmaMSStructState); if (PointersToMembersPragmaLocation.isValid()) { diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index b40e3cf892650d..3cac82ad421c00 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -794,6 +794,9 @@ ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { RD->setNonTrivialToPrimitiveDefaultInitialize(Record.readInt()); RD->setNonTrivialToPrimitiveCopy(Record.readInt()); RD->setNonTrivialToPrimitiveDestroy(Record.readInt()); + RD->setHasNonTrivialToPrimitiveDefaultInitializeCUnion(Record.readInt()); + RD->setHasNonTrivialToPrimitiveDestructCUnion(Record.readInt()); + RD->setHasNonTrivialToPrimitiveCopyCUnion(Record.readInt()); RD->setParamDestroyedInCallee(Record.readInt()); RD->setArgPassingRestrictions((RecordDecl::ArgPassingKind)Record.readInt()); return Redecl; diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 51a1e81525187a..afaaa543bb27fe 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2861,7 +2861,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case STMT_CXX_TRY: S = CXXTryStmt::Create(Context, Empty, - /*NumHandlers=*/Record[ASTStmtReader::NumStmtFields]); + /*numHandlers=*/Record[ASTStmtReader::NumStmtFields]); break; case STMT_CXX_FOR_RANGE: diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index a22e97aaa5cd32..10946f9b0d985d 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1447,7 +1447,7 @@ ASTFileSignature ASTWriter::writeUnhashedControlBlock(Preprocessor &PP, Stream.EmitRecord(DIAGNOSTIC_OPTIONS, Record); // Write out the diagnostic/pragma mappings. - WritePragmaDiagnosticMappings(Diags, /* IsModule = */ WritingModule); + WritePragmaDiagnosticMappings(Diags, /* isModule = */ WritingModule); // Leave the options block. Stream.ExitBlock(); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 3d9dd7131b1de1..b71315505de90e 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -476,6 +476,9 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { Record.push_back(D->isNonTrivialToPrimitiveDefaultInitialize()); Record.push_back(D->isNonTrivialToPrimitiveCopy()); Record.push_back(D->isNonTrivialToPrimitiveDestroy()); + Record.push_back(D->hasNonTrivialToPrimitiveDefaultInitializeCUnion()); + Record.push_back(D->hasNonTrivialToPrimitiveDestructCUnion()); + Record.push_back(D->hasNonTrivialToPrimitiveCopyCUnion()); Record.push_back(D->isParamDestroyedInCallee()); Record.push_back(D->getArgPassingRestrictions()); @@ -1999,6 +2002,12 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNonTrivialToPrimitiveDestroy Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); + // hasNonTrivialToPrimitiveDefaultInitializeCUnion + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); + // hasNonTrivialToPrimitiveDestructCUnion + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); + // hasNonTrivialToPrimitiveCopyCUnion + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isParamDestroyedInCallee Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // getArgPassingRestrictions diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp index f90eab322785ac..2db8f830c46de7 100644 --- a/clang/lib/Serialization/GlobalModuleIndex.cpp +++ b/clang/lib/Serialization/GlobalModuleIndex.cpp @@ -658,8 +658,8 @@ llvm::Error GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { // Find the imported module file. const FileEntry *DependsOnFile - = FileMgr.getFile(ImportedFile, /*openFile=*/false, - /*cacheFailure=*/false); + = FileMgr.getFile(ImportedFile, /*OpenFile=*/false, + /*CacheFailure=*/false); if (!DependsOnFile) return llvm::createStringError(std::errc::bad_file_descriptor, diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index 3e45b30e250bd8..6ae0c4f5755196 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -42,8 +42,8 @@ using namespace clang; using namespace serialization; ModuleFile *ModuleManager::lookupByFileName(StringRef Name) const { - const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false, - /*cacheFailure=*/false); + const FileEntry *Entry = FileMgr.getFile(Name, /*OpenFile=*/false, + /*CacheFailure=*/false); if (Entry) return lookup(Entry); @@ -68,8 +68,8 @@ ModuleFile *ModuleManager::lookup(const FileEntry *File) const { std::unique_ptr ModuleManager::lookupBuffer(StringRef Name) { - const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false, - /*cacheFailure=*/false); + const FileEntry *Entry = FileMgr.getFile(Name, /*OpenFile=*/false, + /*CacheFailure=*/false); return std::move(InMemoryBuffers[Entry]); } @@ -184,7 +184,7 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, } else { // Get a buffer of the file and close the file descriptor when done. Buf = FileMgr.getBufferForFile(NewModule->File, - /*IsVolatile=*/false, + /*isVolatile=*/false, /*ShouldClose=*/true); } @@ -447,7 +447,7 @@ bool ModuleManager::lookupModuleFile(StringRef FileName, // Open the file immediately to ensure there is no race between stat'ing and // opening the file. - File = FileMgr.getFile(FileName, /*openFile=*/true, /*cacheFailure=*/false); + File = FileMgr.getFile(FileName, /*OpenFile=*/true, /*CacheFailure=*/false); if (!File) return false; diff --git a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp index 916a20e559f863..3cfe4dc82a1006 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -144,7 +144,7 @@ static void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD, QualType Ty = Ctx.getPointerType(Ctx.getRecordType(MD->getParent())); ProgramStateRef State = C.getState(); - State = setDynamicTypeInfo(State, Region, Ty, /*CanBeSubclass=*/false); + State = setDynamicTypeInfo(State, Region, Ty, /*CanBeSubClassed=*/false); C.addTransition(State); } @@ -307,7 +307,7 @@ void DynamicTypePropagation::checkPostStmt(const CXXNewExpr *NewE, return; C.addTransition(setDynamicTypeInfo(C.getState(), MR, NewE->getType(), - /*CanBeSubclass=*/false)); + /*CanBeSubClassed=*/false)); } const ObjCObjectType * @@ -887,7 +887,7 @@ void DynamicTypePropagation::checkPostObjCMessage(const ObjCMethodCall &M, // MostSpecializedTypeArgsMap. We should only store anything in the later if // the stored data differs from the one stored in the former. State = setDynamicTypeInfo(State, RetRegion, ResultType, - /*CanBeSubclass=*/true); + /*CanBeSubClassed=*/true); Pred = C.addTransition(State); } diff --git a/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp index 0637c2b29645b5..d471c23b83bfcf 100644 --- a/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/GCDAntipatternChecker.cpp @@ -196,7 +196,7 @@ static void emitDiagnostics(const BoundNodes &Nodes, ADC->getDecl(), Checker, /*Name=*/"GCD performance anti-pattern", - /*Category=*/"Performance", + /*BugCategory=*/"Performance", OS.str(), PathDiagnosticLocation::createBegin(SW, BR.getSourceManager(), ADC), SW->getSourceRange()); diff --git a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp index d575b2fd6ecb32..cc2cfb77422704 100644 --- a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp @@ -115,7 +115,7 @@ bool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) { if (const CompoundStmt *CS = dyn_cast(Stmt1)) { if (!CS->body_empty()) { const IfStmt *InnerIf = dyn_cast(*CS->body_begin()); - if (InnerIf && isIdenticalStmt(AC->getASTContext(), I->getCond(), InnerIf->getCond(), /*ignoreSideEffects=*/ false)) { + if (InnerIf && isIdenticalStmt(AC->getASTContext(), I->getCond(), InnerIf->getCond(), /*IgnoreSideEffects=*/ false)) { PathDiagnosticLocation ELoc(InnerIf->getCond(), BR.getSourceManager(), AC); BR.EmitBasicReport(AC->getDecl(), Checker, "Identical conditions", categories::LogicError, diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 03e779f3c52d82..a79b3418906556 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -17,6 +17,7 @@ #include "clang/AST/ParentMap.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Lexer.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" #include "clang/StaticAnalyzer/Core/Checker.h" @@ -359,6 +360,11 @@ class MallocChecker : public CheckerisReleased()); } +bool MallocChecker::suppressDeallocationsInSuspiciousContexts( + const CallExpr *CE, CheckerContext &C) const { + if (CE->getNumArgs() == 0) + return false; + + StringRef FunctionStr = ""; + if (const auto *FD = dyn_cast(C.getStackFrame()->getDecl())) + if (const Stmt *Body = FD->getBody()) + if (Body->getBeginLoc().isValid()) + FunctionStr = + Lexer::getSourceText(CharSourceRange::getTokenRange( + {FD->getBeginLoc(), Body->getBeginLoc()}), + C.getSourceManager(), C.getLangOpts()); + + // We do not model the Integer Set Library's retain-count based allocation. + if (!FunctionStr.contains("__isl_")) + return false; + + ProgramStateRef State = C.getState(); + + for (const Expr *Arg : CE->arguments()) + if (SymbolRef Sym = C.getSVal(Arg).getAsSymbol()) + if (const RefState *RS = State->get(Sym)) + State = State->set(Sym, RefState::getEscaped(RS)); + + C.addTransition(State); + return true; +} + bool MallocChecker::checkUseAfterFree(SymbolRef Sym, CheckerContext &C, const Stmt *S) const { @@ -2833,7 +2871,6 @@ ProgramStateRef MallocChecker::checkPointerEscapeAux(ProgramStateRef State, if (const RefState *RS = State->get(sym)) { if ((RS->isAllocated() || RS->isAllocatedOfSizeZero()) && CheckRefState(RS)) { - State = State->remove(sym); State = State->set(sym, RefState::getEscaped(RS)); } } diff --git a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp index b7bf9f3db3ff69..af21c84b995b4c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp @@ -478,7 +478,7 @@ void NullabilityChecker::checkEvent(ImplicitNullDerefEvent Event) const { return; const MemRegion *Region = - getTrackRegion(Event.Location, /*CheckSuperregion=*/true); + getTrackRegion(Event.Location, /*CheckSuperRegion=*/true); if (!Region) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp b/clang/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp index 27dadd09d70387..5b9895c338d81e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/OSObjectCStyleCast.cpp @@ -49,7 +49,7 @@ static void emitDiagnostics(const BoundNodes &Nodes, ADC->getDecl(), Checker, /*Name=*/"OSObject C-Style Cast", - /*Category=*/"Security", + /*BugCategory=*/"Security", OS.str(), PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), ADC), CE->getSourceRange()); diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp index 40f82214e94955..d2371fe60d21d1 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp @@ -136,7 +136,7 @@ static void emitDiagnostics(BoundNodes &Match, const Decl *D, BugReporter &BR, ADC->getDecl(), Checker, /*Name=*/(llvm::Twine(ActionMsg) + " autoreleasing out parameter inside autorelease pool").str(), - /*Category=*/"Memory", + /*BugCategory=*/"Memory", (llvm::Twine(ActionMsg) + " autoreleasing out parameter " + (IsCapture ? "'" + PVD->getName() + "'" + " " : "") + "inside " + "autorelease pool that may exit before " + Name + " returns; consider " diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp index 31d2d7c125e263..4a3a8dae23a7f6 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp @@ -951,7 +951,7 @@ bool RetainCountChecker::evalCall(const CallEvent &Call, // And on the original branch assume that both input and // output are non-zero. if (auto L = RetVal.getAs()) - state = state->assume(*L, /*Assumption=*/true); + state = state->assume(*L, /*assumption=*/true); } } diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp index 927e9ae443609e..796fd882ffd5e7 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp @@ -65,7 +65,7 @@ StringRef RefCountBug::getDescription() const { RefCountBug::RefCountBug(const CheckerBase *Checker, RefCountBugType BT) : BugType(Checker, bugTypeToName(BT), categories::MemoryRefCount, - /*SupressOnSink=*/BT == LeakWithinFunction || BT == LeakAtReturn), + /*SuppressOnSink=*/BT == LeakWithinFunction || BT == LeakAtReturn), BT(BT), Checker(Checker) {} static bool isNumericLiteralExpression(const Expr *E) { diff --git a/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp index e744ff9d7c9e58..5e305aa709b64e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp @@ -115,7 +115,7 @@ static void emitDiagnostics(BoundNodes &Match, BR.EmitBasicReport(ADC->getDecl(), Checker, /*Name=*/"Memory leak inside autorelease pool", - /*Category=*/"Memory", + /*BugCategory=*/"Memory", /*Name=*/ (Twine("Temporary objects allocated in the") + " autorelease pool " + diff --git a/clang/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp index 417b07d14be513..62a4c2ab0209c6 100644 --- a/clang/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp @@ -87,7 +87,7 @@ class TrustNonnullChecker : public Checker()) - State = State->assume(*L, /*Assumption=*/true); + State = State->assume(*L, /*assumption=*/true); C.addTransition(State); } @@ -106,7 +106,7 @@ class TrustNonnullChecker : public Checker()) - State = State->assume(*L, /*Assumption=*/true); + State = State->assume(*L, /*assumption=*/true); } // Record an implication: index is non-null if the output is non-null. diff --git a/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp index 95f2b703cdd65b..1b1ffff5ade827 100644 --- a/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp @@ -23,7 +23,7 @@ AnalysisManager::AnalysisManager(ASTContext &ASTCtx, DiagnosticsEngine &diags, : AnaCtxMgr( ASTCtx, Options.UnoptimizedCFG, Options.ShouldIncludeImplicitDtorsInCFG, - /*AddInitializers=*/true, + /*addInitializers=*/true, Options.ShouldIncludeTemporaryDtorsInCFG, Options.ShouldIncludeLifetimeInCFG, // Adding LoopExit elements to the CFG is a requirement for loop diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 6627633f393327..e5a0794f10e2ce 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -1259,7 +1259,7 @@ generateEmptyDiagnosticForReport(BugReport *R, SourceManager &SM) { return llvm::make_unique( R->getBugType().getCheckName(), R->getDeclWithIssue(), R->getBugType().getName(), R->getDescription(), - R->getShortDescription(/*Fallback=*/false), BT.getCategory(), + R->getShortDescription(/*UseFallback=*/false), BT.getCategory(), R->getUniqueingLocation(), R->getUniqueingDecl(), findExecutedLines(SM, R->getErrorNode())); } diff --git a/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp b/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp index 75ae2606910aca..79424452240d71 100644 --- a/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp +++ b/clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp @@ -36,7 +36,7 @@ DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State, // Otherwise, fall back to what we know about the region. if (const auto *TR = dyn_cast(Reg)) - return DynamicTypeInfo(TR->getLocationType(), /*CanBeSubclass=*/false); + return DynamicTypeInfo(TR->getLocationType(), /*CanBeSub=*/false); if (const auto *SR = dyn_cast(Reg)) { SymbolRef Sym = SR->getSymbol(); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 12094c6a1e6c90..1fef5b3c1edd56 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1568,7 +1568,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, ProgramStateRef NewState = createTemporaryRegionIfNeeded(State, LCtx, OCE->getArg(0)); if (NewState != State) { - Pred = Bldr.generateNode(OCE, Pred, NewState, /*Tag=*/nullptr, + Pred = Bldr.generateNode(OCE, Pred, NewState, /*tag=*/nullptr, ProgramPoint::PreStmtKind); // Did we cache out? if (!Pred) diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index e00a08b2162c10..b935e3afe34b2f 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -327,30 +327,30 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) { ExplodedNodeSet DstPostPostCallCallback; getCheckerManager().runCheckersForPostCall(DstPostPostCallCallback, CEENode, *UpdatedCall, *this, - /*WasInlined=*/true); + /*wasInlined=*/true); for (auto I : DstPostPostCallCallback) { getCheckerManager().runCheckersForNewAllocator( CNE, *getObjectUnderConstruction(I->getState(), CNE, calleeCtx->getParent()), DstPostCall, I, *this, - /*WasInlined=*/true); + /*wasInlined=*/true); } } else { getCheckerManager().runCheckersForPostCall(DstPostCall, CEENode, *UpdatedCall, *this, - /*WasInlined=*/true); + /*wasInlined=*/true); } ExplodedNodeSet Dst; if (const ObjCMethodCall *Msg = dyn_cast(Call)) { getCheckerManager().runCheckersForPostObjCMessage(Dst, DstPostCall, *Msg, *this, - /*WasInlined=*/true); + /*wasInlined=*/true); } else if (CE && !(isa(CE) && // Called when visiting CXXNewExpr. AMgr.getAnalyzerOptions().MayInlineCXXAllocator)) { getCheckerManager().runCheckersForPostStmt(Dst, DstPostCall, CE, - *this, /*WasInlined=*/true); + *this, /*wasInlined=*/true); } else { Dst.insert(DstPostCall); } @@ -645,7 +645,7 @@ ProgramStateRef ExprEngine::bindReturnValue(const CallEvent &Call, ITraits.setTrait(TargetR, RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion); State = State->invalidateRegions(TargetR, E, Count, LCtx, - /* CausedByPointerEscape=*/false, nullptr, + /* CausesPointerEscape=*/false, nullptr, &Call, &ITraits); R = State->getSVal(Target.castAs(), E->getType()); diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index a389619f842607..d2aea1fd92ddab 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1253,7 +1253,7 @@ RegionStoreManager::invalidateGlobalRegion(MemRegion::Kind K, // Bind the globals memory space to a new symbol that we will use to derive // the bindings for all globals. const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion(K); - SVal V = svalBuilder.conjureSymbolVal(/* SymbolTag = */ (const void*) GS, Ex, LCtx, + SVal V = svalBuilder.conjureSymbolVal(/* symbolTag = */ (const void*) GS, Ex, LCtx, /* type does not matter */ Ctx.IntTy, Count); diff --git a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index aaf29abd473096..84c52f53ca5e75 100644 --- a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -525,7 +525,7 @@ SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state, case BO_Sub: if (resultTy->isIntegralOrEnumerationType()) return makeIntVal(0, resultTy); - return evalCastFromNonLoc(makeIntVal(0, /*Unsigned=*/false), resultTy); + return evalCastFromNonLoc(makeIntVal(0, /*isUnsigned=*/false), resultTy); case BO_Or: case BO_And: return evalCastFromNonLoc(lhs, resultTy); diff --git a/clang/lib/Tooling/JSONCompilationDatabase.cpp b/clang/lib/Tooling/JSONCompilationDatabase.cpp index 76a82b0fd9bd36..f19a0f7550b960 100644 --- a/clang/lib/Tooling/JSONCompilationDatabase.cpp +++ b/clang/lib/Tooling/JSONCompilationDatabase.cpp @@ -256,15 +256,57 @@ JSONCompilationDatabase::getAllCompileCommands() const { return Commands; } +static llvm::StringRef stripExecutableExtension(llvm::StringRef Name) { + Name.consume_back(".exe"); + return Name; +} + +// There are compiler-wrappers (ccache, distcc, gomacc) that take the "real" +// compiler as an argument, e.g. distcc gcc -O3 foo.c. +// These end up in compile_commands.json when people set CC="distcc gcc". +// Clang's driver doesn't understand this, so we need to unwrap. +static bool unwrapCommand(std::vector &Args) { + if (Args.size() < 2) + return false; + StringRef Wrapper = + stripExecutableExtension(llvm::sys::path::filename(Args.front())); + if (Wrapper == "distcc" || Wrapper == "gomacc" || Wrapper == "ccache") { + // Most of these wrappers support being invoked 3 ways: + // `distcc g++ file.c` This is the mode we're trying to match. + // We need to drop `distcc`. + // `distcc file.c` This acts like compiler is cc or similar. + // Clang's driver can handle this, no change needed. + // `g++ file.c` g++ is a symlink to distcc. + // We don't even notice this case, and all is well. + // + // We need to distinguish between the first and second case. + // The wrappers themselves don't take flags, so Args[1] is a compiler flag, + // an input file, or a compiler. Inputs have extensions, compilers don't. + bool HasCompiler = + (Args[1][0] != '-') && + !llvm::sys::path::has_extension(stripExecutableExtension(Args[1])); + if (HasCompiler) { + Args.erase(Args.begin()); + return true; + } + // If !HasCompiler, wrappers act like GCC. Fine: so do we. + } + return false; +} + static std::vector nodeToCommandLine(JSONCommandLineSyntax Syntax, const std::vector &Nodes) { SmallString<1024> Storage; - if (Nodes.size() == 1) - return unescapeCommandLine(Syntax, Nodes[0]->getValue(Storage)); std::vector Arguments; - for (const auto *Node : Nodes) - Arguments.push_back(Node->getValue(Storage)); + if (Nodes.size() == 1) + Arguments = unescapeCommandLine(Syntax, Nodes[0]->getValue(Storage)); + else + for (const auto *Node : Nodes) + Arguments.push_back(Node->getValue(Storage)); + // There may be multiple wrappers: using distcc and ccache together is common. + while (unwrapCommand(Arguments)) + ; return Arguments; } diff --git a/clang/test/Analysis/cfg-openmp.cpp b/clang/test/Analysis/cfg-openmp.cpp index 2f734d14b0216e..dd417bf408c8f1 100644 --- a/clang/test/Analysis/cfg-openmp.cpp +++ b/clang/test/Analysis/cfg-openmp.cpp @@ -1,340 +1,402 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG %s 2>&1 -fopenmp | FileCheck %s +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG %s 2>&1 -fopenmp -fopenmp-version=45 | FileCheck %s // CHECK-LABEL: void xxx(int argc) void xxx(int argc) { // CHECK: [B1] // CHECK-NEXT: 1: int x; - int x; -// CHECK-NEXT: 2: x -// CHECK-NEXT: 3: [B1.2] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 4: argc -// CHECK-NEXT: 5: [B1.4] = [B1.3] -// CHECK-NEXT: 6: #pragma omp atomic read -// CHECK-NEXT: [B1.5]; +// CHECK-NEXT: 2: int cond; + int x, cond; +// CHECK-NEXT: [[#ATOM:]]: x +// CHECK-NEXT: [[#ATOM+1]]: [B1.[[#ATOM]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#ATOM+2]]: argc +// CHECK-NEXT: [[#ATOM+3]]: [B1.[[#ATOM+2]]] = [B1.[[#ATOM+1]]] +// CHECK-NEXT: [[#ATOM+4]]: #pragma omp atomic read +// CHECK-NEXT: [B1.[[#ATOM+3]]]; #pragma omp atomic read argc = x; -// CHECK-NEXT: 7: x -// CHECK-NEXT: 8: [B1.7] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 9: argc -// CHECK-NEXT: 10: [B1.9] = [B1.8] -// CHECK-NEXT: 11: #pragma omp critical -// CHECK-NEXT: [B1.10]; +// CHECK-NEXT: [[#CRIT:]]: x +// CHECK-NEXT: [[#CRIT+1]]: [B1.[[#CRIT]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#CRIT+2]]: argc +// CHECK-NEXT: [[#CRIT+3]]: [B1.[[#CRIT+2]]] = [B1.[[#CRIT+1]]] +// CHECK-NEXT: [[#CRIT+4]]: #pragma omp critical +// CHECK-NEXT: [B1.[[#CRIT+3]]]; #pragma omp critical argc = x; -// CHECK-NEXT: 12: x -// CHECK-NEXT: 13: [B1.12] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 14: argc -// CHECK-NEXT: 15: [B1.14] = [B1.13] -// CHECK-NEXT: 16: #pragma omp distribute parallel for +// CHECK-NEXT: [[#DPF:]]: x +// CHECK-NEXT: [[#DPF+1]]: [B1.[[#DPF]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#DPF+2]]: argc +// CHECK-NEXT: [[#DPF+3]]: [B1.[[#DPF+2]]] = [B1.[[#DPF+1]]] +// CHECK-NEXT: [[#DPF+4]]: cond +// CHECK-NEXT: [[#DPF+5]]: [B1.[[#DPF+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#DPF+6]]: [B1.[[#DPF+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#DPF+7]]: #pragma omp distribute parallel for if(parallel: cond) // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.15]; -#pragma omp distribute parallel for +// CHECK-NEXT: [B1.[[#DPF+3]]]; +#pragma omp distribute parallel for if(parallel:cond) for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 17: x -// CHECK-NEXT: 18: [B1.17] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 19: argc -// CHECK-NEXT: 20: [B1.19] = [B1.18] -// CHECK-NEXT: 21: #pragma omp distribute parallel for simd +// CHECK-NEXT: [[#DPFS:]]: x +// CHECK-NEXT: [[#DPFS+1]]: [B1.[[#DPFS]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#DPFS+2]]: argc +// CHECK-NEXT: [[#DPFS+3]]: [B1.[[#DPFS+2]]] = [B1.[[#DPFS+1]]] +// CHECK-NEXT: [[#DPFS+4]]: cond +// CHECK-NEXT: [[#DPFS+5]]: [B1.[[#DPFS+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#DPFS+6]]: [B1.[[#DPFS+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#DPFS+7]]: #pragma omp distribute parallel for simd if(cond) // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.20]; -#pragma omp distribute parallel for simd +// CHECK-NEXT: [B1.[[#DPFS+3]]]; +#pragma omp distribute parallel for simd if(cond) for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 22: x -// CHECK-NEXT: 23: [B1.22] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 24: argc -// CHECK-NEXT: 25: [B1.24] = [B1.23] -// CHECK-NEXT: 26: #pragma omp distribute simd +// CHECK-NEXT: [[#DS:]]: x +// CHECK-NEXT: [[#DS+1]]: [B1.[[#DS]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#DS+2]]: argc +// CHECK-NEXT: [[#DS+3]]: [B1.[[#DS+2]]] = [B1.[[#DS+1]]] +// CHECK-NEXT: [[#DS+4]]: #pragma omp distribute simd // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.25]; +// CHECK-NEXT: [B1.[[#DS+3]]]; #pragma omp distribute simd for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 27: x -// CHECK-NEXT: 28: [B1.27] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 29: argc -// CHECK-NEXT: 30: [B1.29] = [B1.28] -// CHECK-NEXT: 31: #pragma omp for +// CHECK-NEXT: [[#FOR:]]: x +// CHECK-NEXT: [[#FOR+1]]: [B1.[[#FOR]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#FOR+2]]: argc +// CHECK-NEXT: [[#FOR+3]]: [B1.[[#FOR+2]]] = [B1.[[#FOR+1]]] +// CHECK-NEXT: [[#FOR+4]]: #pragma omp for // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.30]; +// CHECK-NEXT: [B1.[[#FOR+3]]]; #pragma omp for for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 32: x -// CHECK-NEXT: 33: [B1.32] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 34: argc -// CHECK-NEXT: 35: [B1.34] = [B1.33] -// CHECK-NEXT: 36: #pragma omp for simd +// CHECK-NEXT: [[#FS:]]: x +// CHECK-NEXT: [[#FS+1]]: [B1.[[#FS]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#FS+2]]: argc +// CHECK-NEXT: [[#FS+3]]: [B1.[[#FS+2]]] = [B1.[[#FS+1]]] +// CHECK-NEXT: [[#FS+4]]: #pragma omp for simd // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.35]; +// CHECK-NEXT: [B1.[[#FS+3]]]; #pragma omp for simd for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 37: x -// CHECK-NEXT: 38: [B1.37] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 39: argc -// CHECK-NEXT: 40: [B1.39] = [B1.38] -// CHECK-NEXT: 41: #pragma omp master -// CHECK-NEXT: [B1.40]; +// CHECK-NEXT: [[#MASTER:]]: x +// CHECK-NEXT: [[#MASTER+1]]: [B1.[[#MASTER]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#MASTER+2]]: argc +// CHECK-NEXT: [[#MASTER+3]]: [B1.[[#MASTER+2]]] = [B1.[[#MASTER+1]]] +// CHECK-NEXT: [[#MASTER+4]]: #pragma omp master +// CHECK-NEXT: [B1.[[#MASTER+3]]]; #pragma omp master argc = x; -// CHECK-NEXT: 42: x -// CHECK-NEXT: 43: [B1.42] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 44: argc -// CHECK-NEXT: 45: [B1.44] = [B1.43] -// CHECK-NEXT: 46: #pragma omp ordered -// CHECK-NEXT: [B1.45]; -// CHECK-NEXT: 47: #pragma omp for ordered +// CHECK-NEXT: [[#ORD:]]: x +// CHECK-NEXT: [[#ORD+1]]: [B1.[[#ORD]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#ORD+2]]: argc +// CHECK-NEXT: [[#ORD+3]]: [B1.[[#ORD+2]]] = [B1.[[#ORD+1]]] +// CHECK-NEXT: [[#ORD+4]]: #pragma omp ordered +// CHECK-NEXT: [B1.[[#ORD+3]]]; +// CHECK-NEXT: [[#ORD+5]]: #pragma omp for ordered // CHECK-NEXT: for (int i = 0; i < 10; ++i) { -// CHECK-NEXT:[B1.46] } +// CHECK-NEXT:[B1.[[#ORD+4]]] } #pragma omp for ordered for (int i = 0; i < 10; ++i) { #pragma omp ordered argc = x; } -// CHECK-NEXT: 48: x -// CHECK-NEXT: 49: [B1.48] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 50: argc -// CHECK-NEXT: 51: [B1.50] = [B1.49] -// CHECK-NEXT: 52: #pragma omp parallel for +// CHECK-NEXT: [[#PF:]]: x +// CHECK-NEXT: [[#PF+1]]: [B1.[[#PF]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#PF+2]]: argc +// CHECK-NEXT: [[#PF+3]]: [B1.[[#PF+2]]] = [B1.[[#PF+1]]] +// CHECK-NEXT: [[#PF+4]]: cond +// CHECK-NEXT: [[#PF+5]]: [B1.[[#PF+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#PF+6]]: [B1.[[#PF+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#PF+7]]: #pragma omp parallel for if(cond) // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.51]; -#pragma omp parallel for +// CHECK-NEXT: [B1.[[#PF+3]]]; +#pragma omp parallel for if(cond) for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 53: x -// CHECK-NEXT: 54: [B1.53] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 55: argc -// CHECK-NEXT: 56: [B1.55] = [B1.54] -// CHECK-NEXT: 57: #pragma omp parallel for simd +// CHECK-NEXT: [[#PFS:]]: x +// CHECK-NEXT: [[#PFS+1]]: [B1.[[#PFS]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#PFS+2]]: argc +// CHECK-NEXT: [[#PFS+3]]: [B1.[[#PFS+2]]] = [B1.[[#PFS+1]]] +// CHECK-NEXT: [[#PFS+4]]: cond +// CHECK-NEXT: [[#PFS+5]]: [B1.[[#PFS+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#PFS+6]]: [B1.[[#PFS+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#PFS+7]]: #pragma omp parallel for simd if(cond) // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.56]; -#pragma omp parallel for simd +// CHECK-NEXT: [B1.[[#PFS+3]]]; +#pragma omp parallel for simd if(cond) for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 58: x -// CHECK-NEXT: 59: [B1.58] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 60: argc -// CHECK-NEXT: 61: [B1.60] = [B1.59] -// CHECK-NEXT: 62: #pragma omp parallel -// CHECK-NEXT: [B1.61]; -#pragma omp parallel +// CHECK-NEXT: [[#PAR:]]: x +// CHECK-NEXT: [[#PAR+1]]: [B1.[[#PAR]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#PAR+2]]: argc +// CHECK-NEXT: [[#PAR+3]]: [B1.[[#PAR+2]]] = [B1.[[#PAR+1]]] +// CHECK-NEXT: [[#PAR+4]]: cond +// CHECK-NEXT: [[#PAR+5]]: [B1.[[#PAR+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#PAR+6]]: [B1.[[#PAR+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#PAR+7]]: #pragma omp parallel if(cond) +// CHECK-NEXT: [B1.[[#PAR+3]]]; +#pragma omp parallel if(cond) argc = x; -// CHECK-NEXT: 63: x -// CHECK-NEXT: 64: [B1.63] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 65: argc -// CHECK-NEXT: 66: [B1.65] = [B1.64] -// CHECK-NEXT: 67: #pragma omp parallel sections +// CHECK-NEXT: [[#PSECT:]]: x +// CHECK-NEXT: [[#PSECT+1]]: [B1.[[#PSECT]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#PSECT+2]]: argc +// CHECK-NEXT: [[#PSECT+3]]: [B1.[[#PSECT+2]]] = [B1.[[#PSECT+1]]] +// CHECK-NEXT: [[#PSECT+4]]: cond +// CHECK-NEXT: [[#PSECT+5]]: [B1.[[#PSECT+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#PSECT+6]]: [B1.[[#PSECT+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#PSECT+7]]: #pragma omp parallel sections if(cond) // CHECK-NEXT: { -// CHECK-NEXT: [B1.66]; +// CHECK-NEXT: [B1.[[#PSECT+3]]]; // CHECK-NEXT: } -#pragma omp parallel sections +#pragma omp parallel sections if(cond) { argc = x; } -// CHECK-NEXT: 68: x -// CHECK-NEXT: 69: [B1.68] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 70: argc -// CHECK-NEXT: 71: [B1.70] = [B1.69] -// CHECK-NEXT: 72: #pragma omp simd +// CHECK-NEXT: [[#SIMD:]]: x +// CHECK-NEXT: [[#SIMD+1]]: [B1.[[#SIMD]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#SIMD+2]]: argc +// CHECK-NEXT: [[#SIMD+3]]: [B1.[[#SIMD+2]]] = [B1.[[#SIMD+1]]] +// CHECK-NEXT: [[#SIMD+4]]: #pragma omp simd // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.71]; +// CHECK-NEXT: [B1.[[#SIMD+3]]]; #pragma omp simd for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 73: x -// CHECK-NEXT: 74: [B1.73] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 75: argc -// CHECK-NEXT: 76: [B1.75] = [B1.74] -// CHECK-NEXT: 77: #pragma omp single -// CHECK-NEXT: [B1.76]; +// CHECK-NEXT: [[#SINGLE:]]: x +// CHECK-NEXT: [[#SINGLE+1]]: [B1.[[#SINGLE]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#SINGLE+2]]: argc +// CHECK-NEXT: [[#SINGLE+3]]: [B1.[[#SINGLE+2]]] = [B1.[[#SINGLE+1]]] +// CHECK-NEXT: [[#SINGLE+4]]: #pragma omp single +// CHECK-NEXT: [B1.[[#SINGLE+3]]]; #pragma omp single argc = x; -// CHECK-NEXT: 78: x -// CHECK-NEXT: 79: [B1.78] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 80: argc -// CHECK-NEXT: 81: [B1.80] = [B1.79] -// CHECK-NEXT: 82: #pragma omp target depend(in : argc) -// CHECK-NEXT: [B1.81]; +// CHECK-NEXT: [[#TARGET:]]: x +// CHECK-NEXT: [[#TARGET+1]]: [B1.[[#TARGET]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TARGET+2]]: argc +// CHECK-NEXT: [[#TARGET+3]]: [B1.[[#TARGET+2]]] = [B1.[[#TARGET+1]]] +// CHECK-NEXT: [[#TARGET+4]]: cond +// CHECK-NEXT: [[#TARGET+5]]: [B1.[[#TARGET+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TARGET+6]]: [B1.[[#TARGET+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TARGET+7]]: #pragma omp target depend(in : argc) if(cond) +// CHECK-NEXT: [B1.[[#TARGET+3]]]; #pragma omp target depend(in \ - : argc) + : argc) if(cond) argc = x; -// CHECK-NEXT: 83: x -// CHECK-NEXT: 84: [B1.83] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 85: argc -// CHECK-NEXT: 86: [B1.85] = [B1.84] -// CHECK-NEXT: 87: #pragma omp target parallel for +// CHECK-NEXT: [[#TPF:]]: x +// CHECK-NEXT: [[#TPF+1]]: [B1.[[#TPF]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TPF+2]]: argc +// CHECK-NEXT: [[#TPF+3]]: [B1.[[#TPF+2]]] = [B1.[[#TPF+1]]] +// CHECK-NEXT: [[#TPF+4]]: cond +// CHECK-NEXT: [[#TPF+5]]: [B1.[[#TPF+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TPF+6]]: [B1.[[#TPF+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TPF+7]]: #pragma omp target parallel for if(parallel: cond) // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.86]; -#pragma omp target parallel for +// CHECK-NEXT: [B1.[[#TPF+3]]]; +#pragma omp target parallel for if(parallel:cond) for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 88: x -// CHECK-NEXT: 89: [B1.88] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 90: argc -// CHECK-NEXT: 91: [B1.90] = [B1.89] -// CHECK-NEXT: 92: #pragma omp target parallel for simd +// CHECK-NEXT: [[#TPFS:]]: x +// CHECK-NEXT: [[#TPFS+1]]: [B1.[[#TPFS]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TPFS+2]]: argc +// CHECK-NEXT: [[#TPFS+3]]: [B1.[[#TPFS+2]]] = [B1.[[#TPFS+1]]] +// CHECK-NEXT: [[#TPFS+4]]: cond +// CHECK-NEXT: [[#TPFS+5]]: [B1.[[#TPFS+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TPFS+6]]: [B1.[[#TPFS+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TPFS+7]]: #pragma omp target parallel for simd if(target: cond) // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.91]; -#pragma omp target parallel for simd +// CHECK-NEXT: [B1.[[#TPFS+3]]]; +#pragma omp target parallel for simd if(target:cond) for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 93: x -// CHECK-NEXT: 94: [B1.93] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 95: argc -// CHECK-NEXT: 96: [B1.95] = [B1.94] -// CHECK-NEXT: 97: #pragma omp target parallel -// CHECK-NEXT: [B1.96]; -#pragma omp target parallel +// CHECK-NEXT: [[#TP:]]: x +// CHECK-NEXT: [[#TP+1]]: [B1.[[#TP]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TP+2]]: argc +// CHECK-NEXT: [[#TP+3]]: [B1.[[#TP+2]]] = [B1.[[#TP+1]]] +// CHECK-NEXT: [[#TP+4]]: cond +// CHECK-NEXT: [[#TP+5]]: [B1.[[#TP+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TP+6]]: [B1.[[#TP+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TP+7]]: #pragma omp target parallel if(cond) +// CHECK-NEXT: [B1.[[#TP+3]]]; +#pragma omp target parallel if(cond) argc = x; -// CHECK-NEXT: 98: x -// CHECK-NEXT: 99: [B1.98] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 100: argc -// CHECK-NEXT: 101: [B1.100] = [B1.99] -// CHECK-NEXT: 102: #pragma omp target simd +// CHECK-NEXT: [[#TSIMD:]]: x +// CHECK-NEXT: [[#TSIMD+1]]: [B1.[[#TSIMD]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TSIMD+2]]: argc +// CHECK-NEXT: [[#TSIMD+3]]: [B1.[[#TSIMD+2]]] = [B1.[[#TSIMD+1]]] +// CHECK-NEXT: [[#TSIMD+4]]: cond +// CHECK-NEXT: [[#TSIMD+5]]: [B1.[[#TSIMD+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TSIMD+6]]: [B1.[[#TSIMD+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TSIMD+7]]: #pragma omp target simd if(cond) // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.101]; -#pragma omp target simd +// CHECK-NEXT: [B1.[[#TSIMD+3]]]; +#pragma omp target simd if(cond) for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 103: x -// CHECK-NEXT: 104: [B1.103] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 105: argc -// CHECK-NEXT: 106: [B1.105] = [B1.104] -// CHECK-NEXT: 107: #pragma omp target teams distribute +// CHECK-NEXT: [[#TTD:]]: x +// CHECK-NEXT: [[#TTD+1]]: [B1.[[#TTD]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TTD+2]]: argc +// CHECK-NEXT: [[#TTD+3]]: [B1.[[#TTD+2]]] = [B1.[[#TTD+1]]] +// CHECK-NEXT: [[#TTD+4]]: cond +// CHECK-NEXT: [[#TTD+5]]: [B1.[[#TTD+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TTD+6]]: [B1.[[#TTD+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TTD+7]]: #pragma omp target teams distribute if(cond) // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.106]; -#pragma omp target teams distribute +// CHECK-NEXT: [B1.[[#TTD+3]]]; +#pragma omp target teams distribute if(cond) for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 108: x -// CHECK-NEXT: 109: [B1.108] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 110: argc -// CHECK-NEXT: 111: [B1.110] = [B1.109] -// CHECK-NEXT: 112: #pragma omp target teams distribute parallel for +// CHECK-NEXT: [[#TTDPF:]]: x +// CHECK-NEXT: [[#TTDPF+1]]: [B1.[[#TTDPF]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TTDPF+2]]: argc +// CHECK-NEXT: [[#TTDPF+3]]: [B1.[[#TTDPF+2]]] = [B1.[[#TTDPF+1]]] +// CHECK-NEXT: [[#TTDPF+4]]: cond +// CHECK-NEXT: [[#TTDPF+5]]: [B1.[[#TTDPF+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TTDPF+6]]: [B1.[[#TTDPF+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TTDPF+7]]: #pragma omp target teams distribute parallel for if(cond) // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.111]; -#pragma omp target teams distribute parallel for +// CHECK-NEXT: [B1.[[#TTDPF+3]]]; +#pragma omp target teams distribute parallel for if(cond) for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 113: x -// CHECK-NEXT: 114: [B1.113] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 115: argc -// CHECK-NEXT: 116: [B1.115] = [B1.114] -// CHECK-NEXT: 117: #pragma omp target teams distribute parallel for simd +// CHECK-NEXT: [[#TTDPFS:]]: x +// CHECK-NEXT: [[#TTDPFS+1]]: [B1.[[#TTDPFS]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TTDPFS+2]]: argc +// CHECK-NEXT: [[#TTDPFS+3]]: [B1.[[#TTDPFS+2]]] = [B1.[[#TTDPFS+1]]] +// CHECK-NEXT: [[#TTDPFS+4]]: cond +// CHECK-NEXT: [[#TTDPFS+5]]: [B1.[[#TTDPFS+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TTDPFS+6]]: [B1.[[#TTDPFS+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TTDPFS+7]]: #pragma omp target teams distribute parallel for simd if(parallel: cond) // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.116]; -#pragma omp target teams distribute parallel for simd +// CHECK-NEXT: [B1.[[#TTDPFS+3]]]; +#pragma omp target teams distribute parallel for simd if(parallel:cond) for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 118: x -// CHECK-NEXT: 119: [B1.118] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 120: argc -// CHECK-NEXT: 121: [B1.120] = [B1.119] -// CHECK-NEXT: 122: #pragma omp target teams distribute simd +// CHECK-NEXT: [[#TTDS:]]: x +// CHECK-NEXT: [[#TTDS+1]]: [B1.[[#TTDS]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TTDS+2]]: argc +// CHECK-NEXT: [[#TTDS+3]]: [B1.[[#TTDS+2]]] = [B1.[[#TTDS+1]]] +// CHECK-NEXT: [[#TTDS+4]]: cond +// CHECK-NEXT: [[#TTDS+5]]: [B1.[[#TTDS+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TTDS+6]]: [B1.[[#TTDS+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TTDS+7]]: #pragma omp target teams distribute simd if(cond) // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.121]; -#pragma omp target teams distribute simd +// CHECK-NEXT: [B1.[[#TTDS+3]]]; +#pragma omp target teams distribute simd if(cond) for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 123: x -// CHECK-NEXT: 124: [B1.123] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 125: argc -// CHECK-NEXT: 126: [B1.125] = [B1.124] -// CHECK-NEXT: 127: #pragma omp target teams -// CHECK-NEXT: [B1.126]; -#pragma omp target teams +// CHECK-NEXT: [[#TT:]]: x +// CHECK-NEXT: [[#TT+1]]: [B1.[[#TT]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TT+2]]: argc +// CHECK-NEXT: [[#TT+3]]: [B1.[[#TT+2]]] = [B1.[[#TT+1]]] +// CHECK-NEXT: [[#TT+4]]: cond +// CHECK-NEXT: [[#TT+5]]: [B1.[[#TT+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TT+6]]: [B1.[[#TT+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TT+7]]: #pragma omp target teams if(cond) +// CHECK-NEXT: [B1.[[#TT+3]]]; +#pragma omp target teams if(cond) argc = x; -// CHECK-NEXT: 128: #pragma omp target update to(x) -#pragma omp target update to(x) -// CHECK-NEXT: 129: x -// CHECK-NEXT: 130: [B1.129] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 131: argc -// CHECK-NEXT: 132: [B1.131] = [B1.130] +// CHECK-NEXT: [[#TU:]]: cond +// CHECK-NEXT: [[#TU+1]]: [B1.[[#TU]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TU+2]]: [B1.[[#TU+1]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TU+3]]: #pragma omp target update to(x) if(target update: cond) +#pragma omp target update to(x) if(target update:cond) +// CHECK-NEXT: [[#TASK:]]: x +// CHECK-NEXT: [[#TASK+1]]: [B1.[[#TASK]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TASK+2]]: argc +// CHECK-NEXT: [[#TASK+3]]: [B1.[[#TASK+2]]] = [B1.[[#TASK+1]]] +// CHECK-NEXT: [[#TASK+4]]: cond +// CHECK-NEXT: [[#TASK+5]]: [B1.[[#TASK+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TASK+6]]: [B1.[[#TASK+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TASK+7]]: #pragma omp task if(cond) +// CHECK-NEXT: [B1.[[#TASK+3]]]; +#pragma omp task if(cond) argc = x; -// CHECK-NEXT: 133: x -// CHECK-NEXT: 134: [B1.133] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 135: argc -// CHECK-NEXT: 136: [B1.135] = [B1.134] -// CHECK-NEXT: 137: #pragma omp task -// CHECK-NEXT: [B1.136]; -#pragma omp task - argc = x; -// CHECK-NEXT: 138: x -// CHECK-NEXT: 139: [B1.138] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 140: argc -// CHECK-NEXT: 141: [B1.140] = [B1.139] -// CHECK-NEXT: 142: #pragma omp taskgroup -// CHECK-NEXT: [B1.141]; +// CHECK-NEXT: [[#TG:]]: x +// CHECK-NEXT: [[#TG+1]]: [B1.[[#TG]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TG+2]]: argc +// CHECK-NEXT: [[#TG+3]]: [B1.[[#TG+2]]] = [B1.[[#TG+1]]] +// CHECK-NEXT: [[#TG+4]]: #pragma omp taskgroup +// CHECK-NEXT: [B1.[[#TG+3]]]; #pragma omp taskgroup argc = x; -// CHECK-NEXT: 143: x -// CHECK-NEXT: 144: [B1.143] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 145: argc -// CHECK-NEXT: 146: [B1.145] = [B1.144] -// CHECK-NEXT: 147: #pragma omp taskloop +// CHECK-NEXT: [[#TL:]]: x +// CHECK-NEXT: [[#TL+1]]: [B1.[[#TL]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TL+2]]: argc +// CHECK-NEXT: [[#TL+3]]: [B1.[[#TL+2]]] = [B1.[[#TL+1]]] +// CHECK-NEXT: [[#TL+4]]: cond +// CHECK-NEXT: [[#TL+5]]: [B1.[[#TL+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TL+6]]: [B1.[[#TL+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TL+7]]: #pragma omp taskloop if(cond) // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.146]; -#pragma omp taskloop +// CHECK-NEXT: [B1.[[#TL+3]]]; +#pragma omp taskloop if(cond) for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 148: x -// CHECK-NEXT: 149: [B1.148] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 150: argc -// CHECK-NEXT: 151: [B1.150] = [B1.149] -// CHECK-NEXT: 152: #pragma omp taskloop simd +// CHECK-NEXT: [[#TLS:]]: x +// CHECK-NEXT: [[#TLS+1]]: [B1.[[#TLS]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TLS+2]]: argc +// CHECK-NEXT: [[#TLS+3]]: [B1.[[#TLS+2]]] = [B1.[[#TLS+1]]] +// CHECK-NEXT: [[#TLS+4]]: cond +// CHECK-NEXT: [[#TLS+5]]: [B1.[[#TLS+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TLS+6]]: [B1.[[#TLS+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TLS+7]]: #pragma omp taskloop simd if(cond) // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.151]; -#pragma omp taskloop simd +// CHECK-NEXT: [B1.[[#TLS+3]]]; +#pragma omp taskloop simd if(cond) for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT: 153: x -// CHECK-NEXT: 154: [B1.153] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 155: argc -// CHECK-NEXT: 156: [B1.155] = [B1.154] -// CHECK-NEXT: 157: #pragma omp teams distribute parallel for +// CHECK-NEXT: [[#TDPF:]]: x +// CHECK-NEXT: [[#TDPF+1]]: [B1.[[#TDPF]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TDPF+2]]: argc +// CHECK-NEXT: [[#TDPF+3]]: [B1.[[#TDPF+2]]] = [B1.[[#TDPF+1]]] +// CHECK-NEXT: [[#TDPF+4]]: cond +// CHECK-NEXT: [[#TDPF+5]]: [B1.[[#TDPF+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TDPF+6]]: [B1.[[#TDPF+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TDPF+7]]: #pragma omp teams distribute parallel for if(cond) // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.156]; -// CHECK-NEXT: 158: #pragma omp target +// CHECK-NEXT: [B1.[[#TDPF+3]]]; +// CHECK-NEXT: [[#TDPF+8]]: #pragma omp target #pragma omp target -#pragma omp teams distribute parallel for +#pragma omp teams distribute parallel for if(cond) for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT:[B1.157] 159: x -// CHECK-NEXT: 160: [B1.159] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 161: argc -// CHECK-NEXT: 162: [B1.161] = [B1.160] -// CHECK-NEXT: 163: #pragma omp teams distribute parallel for simd +// CHECK-NEXT: [B1.[[#TDPF+7]]] [[#TDPFS:]]: x +// CHECK-NEXT: [[#TDPFS+1]]: [B1.[[#TDPFS]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TDPFS+2]]: argc +// CHECK-NEXT: [[#TDPFS+3]]: [B1.[[#TDPFS+2]]] = [B1.[[#TDPFS+1]]] +// CHECK-NEXT: [[#TDPFS+4]]: cond +// CHECK-NEXT: [[#TDPFS+5]]: [B1.[[#TDPFS+4]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TDPFS+6]]: [B1.[[#TDPFS+5]]] (ImplicitCastExpr, IntegralToBoolean, _Bool) +// CHECK-NEXT: [[#TDPFS+7]]: #pragma omp teams distribute parallel for simd if(cond) // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.162]; -// CHECK-NEXT: 164: #pragma omp target +// CHECK-NEXT: [B1.[[#TDPFS+3]]]; +// CHECK-NEXT: [[#TDPFS+8]]: #pragma omp target #pragma omp target -#pragma omp teams distribute parallel for simd +#pragma omp teams distribute parallel for simd if(cond) for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT:[B1.163] 165: x -// CHECK-NEXT: 166: [B1.165] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 167: argc -// CHECK-NEXT: 168: [B1.167] = [B1.166] -// CHECK-NEXT: 169: #pragma omp teams distribute simd +// CHECK-NEXT: [B1.[[#TDPFS+7]]] [[#TDS:]]: x +// CHECK-NEXT: [[#TDS+1]]: [B1.[[#TDS]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TDS+2]]: argc +// CHECK-NEXT: [[#TDS+3]]: [B1.[[#TDS+2]]] = [B1.[[#TDS+1]]] +// CHECK-NEXT: [[#TDS+4]]: #pragma omp teams distribute simd // CHECK-NEXT: for (int i = 0; i < 10; ++i) -// CHECK-NEXT: [B1.168]; -// CHECK-NEXT: 170: #pragma omp target +// CHECK-NEXT: [B1.[[#TDS+3]]]; +// CHECK-NEXT: [[#TDS+5]]: #pragma omp target #pragma omp target #pragma omp teams distribute simd for (int i = 0; i < 10; ++i) argc = x; -// CHECK-NEXT:[B1.169] 171: x -// CHECK-NEXT: 172: [B1.171] (ImplicitCastExpr, LValueToRValue, int) -// CHECK-NEXT: 173: argc -// CHECK-NEXT: 174: [B1.173] = [B1.172] -// CHECK-NEXT: 175: #pragma omp teams -// CHECK-NEXT: [B1.174]; -// CHECK-NEXT: 176: #pragma omp target +// CHECK-NEXT: [B1.[[#TDS+4]]] [[#TEAMS:]]: x +// CHECK-NEXT: [[#TEAMS+1]]: [B1.[[#TEAMS]]] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: [[#TEAMS+2]]: argc +// CHECK-NEXT: [[#TEAMS+3]]: [B1.[[#TEAMS+2]]] = [B1.[[#TEAMS+1]]] +// CHECK-NEXT: [[#TEAMS+4]]: #pragma omp teams +// CHECK-NEXT: [B1.[[#TEAMS+3]]]; +// CHECK-NEXT: [[#TEAMS+5]]: #pragma omp target #pragma omp target #pragma omp teams argc = x; -// CHECK-NEXT:[B1.175] Preds +// CHECK-NEXT: [B1.[[#TEAMS+4]]] Preds } diff --git a/clang/test/Analysis/openmp-unsupported.c b/clang/test/Analysis/openmp-unsupported.c index 7e363eecbaa084..b2e1a1b0217978 100644 --- a/clang/test/Analysis/openmp-unsupported.c +++ b/clang/test/Analysis/openmp-unsupported.c @@ -4,4 +4,8 @@ void openmp_parallel_crash_test() { #pragma omp parallel ; +#pragma omp parallel for + for (int i = 0; i < 8; ++i) + for (int j = 0, k = 0; j < 8; ++j) + ; } diff --git a/clang/test/Analysis/retain-count-alloc.cpp b/clang/test/Analysis/retain-count-alloc.cpp new file mode 100644 index 00000000000000..472cbbf0705e2f --- /dev/null +++ b/clang/test/Analysis/retain-count-alloc.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=core,unix.Malloc \ +// RUN: -verify %s + +// expected-no-diagnostics: We do not model Integer Set Library's retain-count +// based allocation. If any of the parameters has an +// '__isl_' prefixed macro definition we escape every +// of them when we are about to 'free()' something. + +#define __isl_take +#define __isl_keep + +struct Object { int Ref; }; +void free(void *); + +Object *copyObj(__isl_keep Object *O) { + O->Ref++; + return O; +} + +void freeObj(__isl_take Object *O) { + if (--O->Ref > 0) + return; + + free(O); // Here we notice that the parameter contains '__isl_', escape it. +} + +void useAfterFree(__isl_take Object *A) { + if (!A) + return; + + Object *B = copyObj(A); + freeObj(B); + + A->Ref = 13; + // no-warning: 'Use of memory after it is freed' was here. +} diff --git a/clang/test/CodeGen/aarch64-vpcs.c b/clang/test/CodeGen/aarch64-vpcs.c index a9edb7490c630b..7e4f50cb87badf 100644 --- a/clang/test/CodeGen/aarch64-vpcs.c +++ b/clang/test/CodeGen/aarch64-vpcs.c @@ -2,7 +2,7 @@ // RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -x c++ -o - %s | FileCheck %s -check-prefix=CHECKCXX // RUN: %clang_cc1 -triple i686-pc-linux-gnu -verify %s -void __attribute__((aarch64_vector_pcs)) f(int *); // expected-warning {{'aarch64_vector_pcs' calling convention ignored for this target}} +void __attribute__((aarch64_vector_pcs)) f(int *); // expected-warning {{'aarch64_vector_pcs' calling convention is not supported for this target}} // CHECKC: define void @g( // CHECKCXX: define void @_Z1gPi( @@ -16,7 +16,7 @@ void g(int *a) { // CHECKC: declare aarch64_vector_pcs void @f( // CHECKCXX: declare aarch64_vector_pcs void @_Z1fPi -void __attribute__((aarch64_vector_pcs)) h(int *a){ // expected-warning {{'aarch64_vector_pcs' calling convention ignored for this target}} +void __attribute__((aarch64_vector_pcs)) h(int *a){ // expected-warning {{'aarch64_vector_pcs' calling convention is not supported for this target}} // CHECKC: define aarch64_vector_pcs void @h( // CHECKCXX: define aarch64_vector_pcs void @_Z1hPi( f(a); diff --git a/clang/test/CodeGen/arm-target-features.c b/clang/test/CodeGen/arm-target-features.c index ec165aeec28812..a0fbafc5d0c54a 100644 --- a/clang/test/CodeGen/arm-target-features.c +++ b/clang/test/CodeGen/arm-target-features.c @@ -32,7 +32,7 @@ // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m4 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V82 // RUN: %clang_cc1 -triple thumbv8-linux-gnueabihf -target-cpu exynos-m5 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V82 -// CHECK-BASIC-V82: "target-features"="+armv8.2-a,+crc,+crypto,+d32,+dotprod,+dsp,+fp-armv8,+fp-armv8d16,+fp-armv8d16sp,+fp-armv8sp,+fp16,+fp64,+fpregs,+hwdiv,+hwdiv-arm,+neon,+ras,+thumb-mode,+vfp2,+vfp2d16,+vfp2d16sp,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,+vfp4,+vfp4d16,+vfp4d16sp,+vfp4sp" +// CHECK-BASIC-V82: "target-features"="+armv8.2-a,+crc,+crypto,+d32,+dotprod,+dsp,+fp-armv8,+fp-armv8d16,+fp-armv8d16sp,+fp-armv8sp,+fp16,+fp64,+fpregs,+fullfp16,+hwdiv,+hwdiv-arm,+neon,+ras,+thumb-mode,+vfp2,+vfp2d16,+vfp2d16sp,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,+vfp4,+vfp4d16,+vfp4d16sp,+vfp4sp" // RUN: %clang_cc1 -triple armv8-linux-gnueabi -target-cpu cortex-a53 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-BASIC-V8-ARM // CHECK-BASIC-V8-ARM: "target-features"="+armv8-a,+crc,+crypto,+d32,+dsp,+fp-armv8,+fp-armv8d16,+fp-armv8d16sp,+fp-armv8sp,+fp16,+fp64,+fpregs,+hwdiv,+hwdiv-arm,+neon,+vfp2,+vfp2d16,+vfp2d16sp,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,+vfp4,+vfp4d16,+vfp4d16sp,+vfp4sp,-thumb-mode" diff --git a/clang/test/CodeGen/arm_acle.c b/clang/test/CodeGen/arm_acle.c index e8a744372de2bb..beca9373506781 100644 --- a/clang/test/CodeGen/arm_acle.c +++ b/clang/test/CodeGen/arm_acle.c @@ -2,6 +2,9 @@ // RUN: %clang_cc1 -ffreestanding -triple armv8-eabi -target-cpu cortex-a57 -O2 -fexperimental-new-pass-manager -S -emit-llvm -o - %s | FileCheck %s -check-prefix=ARM -check-prefix=AArch32 -check-prefix=ARM-NEWPM -check-prefix=AArch32-NEWPM // RUN: %clang_cc1 -ffreestanding -triple aarch64-eabi -target-cpu cortex-a57 -target-feature +neon -target-feature +crc -target-feature +crypto -O2 -fno-experimental-new-pass-manager -S -emit-llvm -o - %s | FileCheck %s -check-prefix=ARM -check-prefix=AArch64 -check-prefix=ARM-LEGACY -check-prefix=AArch64-LEGACY // RUN: %clang_cc1 -ffreestanding -triple aarch64-eabi -target-cpu cortex-a57 -target-feature +neon -target-feature +crc -target-feature +crypto -O2 -fexperimental-new-pass-manager -S -emit-llvm -o - %s | FileCheck %s -check-prefix=ARM -check-prefix=AArch64 -check-prefix=ARM-NEWPM -check-prefix=AArch64-NEWPM +// RUN: %clang_cc1 -ffreestanding -triple aarch64-eabi -target-cpu cortex-a57 -target-feature +v8.3a -O2 -fexperimental-new-pass-manager -S -emit-llvm -o - %s | FileCheck %s -check-prefix=AArch64-v8_3 +// RUN: %clang_cc1 -ffreestanding -triple aarch64-eabi -target-cpu cortex-a57 -target-feature +v8.4a -O2 -fexperimental-new-pass-manager -S -emit-llvm -o - %s | FileCheck %s -check-prefix=AArch64-v8_3 +// RUN: %clang_cc1 -ffreestanding -triple aarch64-eabi -target-cpu cortex-a57 -target-feature +v8.5a -O2 -fexperimental-new-pass-manager -S -emit-llvm -o - %s | FileCheck %s -check-prefix=AArch64-v8_3 #include @@ -823,3 +826,11 @@ void test_wsrp(void *v) { // AArch64: ![[M0]] = !{!"1:2:3:4:5"} // AArch64: ![[M1]] = !{!"sysreg"} + +// AArch64-v8_3-LABEL: @test_jcvt( +// AArch64-v8_3: call i32 @llvm.aarch64.fjcvtzs +#ifdef __ARM_64BIT_STATE +int32_t test_jcvt(double v) { + return __jcvt(v); +} +#endif diff --git a/clang/test/CodeGen/builtin-preserve-access-index.c b/clang/test/CodeGen/builtin-preserve-access-index.c new file mode 100644 index 00000000000000..954a3b827d25a3 --- /dev/null +++ b/clang/test/CodeGen/builtin-preserve-access-index.c @@ -0,0 +1,177 @@ +// RUN: %clang -target x86_64 -emit-llvm -S -g %s -o - | FileCheck %s + +#define _(x) (__builtin_preserve_access_index(x)) + +const void *unit1(const void *arg) { + return _(arg); +} +// CHECK: define dso_local i8* @unit1 +// CHECK-NOT: llvm.preserve.array.access.index +// CHECK-NOT: llvm.preserve.struct.access.index +// CHECK-NOT: llvm.preserve.union.access.index + +const void *unit2(void) { + return _((const void *)0xffffffffFFFF0000ULL); +} +// CHECK: define dso_local i8* @unit2 +// CHECK-NOT: llvm.preserve.array.access.index +// CHECK-NOT: llvm.preserve.struct.access.index +// CHECK-NOT: llvm.preserve.union.access.index + +const void *unit3(const int *arg) { + return _(arg + 1); +} +// CHECK: define dso_local i8* @unit3 +// CHECK-NOT: llvm.preserve.array.access.index +// CHECK-NOT: llvm.preserve.struct.access.index +// CHECK-NOT: llvm.preserve.union.access.index + +const void *unit4(const int *arg) { + return _(&arg[1]); +} +// CHECK: define dso_local i8* @unit4 +// CHECK-NOT: getelementptr +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 1) + +const void *unit5(const int *arg[5]) { + return _(&arg[1][2]); +} +// CHECK: define dso_local i8* @unit5 +// CHECK-NOT: getelementptr +// CHECK: call i32** @llvm.preserve.array.access.index.p0p0i32.p0p0i32(i32** %{{[0-9a-z]+}}, i32 0, i32 1) +// CHECK-NOT: getelementptr +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0i32(i32* %{{[0-9a-z]+}}, i32 0, i32 2) + +struct s1 { + char a; + int b; +}; + +struct s2 { + char a1:1; + char a2:1; + int b; +}; + +struct s3 { + char a1:1; + char a2:1; + char :6; + int b; +}; + +const void *unit6(struct s1 *arg) { + return _(&arg->a); +} +// CHECK: define dso_local i8* @unit6 +// CHECK-NOT: getelementptr +// CHECK: call i8* @llvm.preserve.struct.access.index.p0i8.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] + +const void *unit7(struct s1 *arg) { + return _(&arg->b); +} +// CHECK: define dso_local i8* @unit7 +// CHECK-NOT: getelementptr +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1]] + +const void *unit8(struct s2 *arg) { + return _(&arg->b); +} +// CHECK: define dso_local i8* @unit8 +// CHECK-NOT: getelementptr +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s2s(%struct.s2* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S2:[0-9]+]] + +const void *unit9(struct s3 *arg) { + return _(&arg->b); +} +// CHECK: define dso_local i8* @unit9 +// CHECK-NOT: getelementptr +// CHECK: call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s3s(%struct.s3* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S3:[0-9]+]] + +union u1 { + char a; + int b; +}; + +union u2 { + char a; + int :32; + int b; +}; + +const void *unit10(union u1 *arg) { + return _(&arg->a); +} +// CHECK: define dso_local i8* @unit10 +// CHECK-NOT: getelementptr +// CHECK: call %union.u1* @llvm.preserve.union.access.index.p0s_union.u1s.p0s_union.u1s(%union.u1* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U1:[0-9]+]] + +const void *unit11(union u1 *arg) { + return _(&arg->b); +} +// CHECK: define dso_local i8* @unit11 +// CHECK-NOT: getelementptr +// CHECK: call %union.u1* @llvm.preserve.union.access.index.p0s_union.u1s.p0s_union.u1s(%union.u1* %{{[0-9a-z]+}}, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U1]] + +const void *unit12(union u2 *arg) { + return _(&arg->b); +} +// CHECK: define dso_local i8* @unit12 +// CHECK-NOT: getelementptr +// CHECK: call %union.u2* @llvm.preserve.union.access.index.p0s_union.u2s.p0s_union.u2s(%union.u2* %{{[0-9a-z]+}}, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U2:[0-9]+]] + +struct s4 { + char d; + union u { + int b[4]; + char a; + } c; +}; + +union u3 { + struct s { + int b[4]; + } c; + char a; +}; + +const void *unit13(struct s4 *arg) { + return _(&arg->c.b[2]); +} +// CHECK: define dso_local i8* @unit13 +// CHECK: call %union.u* @llvm.preserve.struct.access.index.p0s_union.us.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S4:[0-9]+]] +// CHECK: call %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_I_U:[0-9]+]] +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2) + +const void *unit14(union u3 *arg) { + return _(&arg->c.b[2]); +} +// CHECK: define dso_local i8* @unit14 +// CHECK: call %union.u3* @llvm.preserve.union.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U3:[0-9]+]] +// CHECK: call [4 x i32]* @llvm.preserve.struct.access.index.p0a4i32.p0s_struct.ss(%struct.s* %{{[0-9a-z]+}}, i32 0, i32 0), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_I_S:[0-9]+]] +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2) + +const void *unit15(struct s4 *arg) { + return _(&arg[2].c.a); +} +// CHECK: define dso_local i8* @unit15 +// CHECK: call %struct.s4* @llvm.preserve.array.access.index.p0s_struct.s4s.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 0, i32 2) +// CHECK: call %union.u* @llvm.preserve.struct.access.index.p0s_union.us.p0s_struct.s4s(%struct.s4* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S4]] +// CHECK: call %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u* %{{[0-9a-z]+}}, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_I_U]] + +const void *unit16(union u3 *arg) { + return _(&arg[2].a); +} +// CHECK: define dso_local i8* @unit16 +// CHECK: call %union.u3* @llvm.preserve.array.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 0, i32 2) +// CHECK: call %union.u3* @llvm.preserve.union.access.index.p0s_union.u3s.p0s_union.u3s(%union.u3* %{{[0-9a-z]+}}, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[UNION_U3]] + +// CHECK: ![[STRUCT_S1]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s1" +// CHECK: ![[STRUCT_S2]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s2" +// CHECK: ![[STRUCT_S3]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s3" +// CHECK: ![[UNION_U1]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u1" +// CHECK: ![[UNION_U2]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u2" +// CHECK: ![[STRUCT_S4]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s4" +// CHECK: ![[UNION_I_U]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u" +// CHECK: ![[UNION_U3]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u3" +// CHECK: ![[STRUCT_I_S]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s" diff --git a/clang/test/CodeGen/builtins-arm64.c b/clang/test/CodeGen/builtins-arm64.c index f164c2f6f3647c..5ec63fba82b5bb 100644 --- a/clang/test/CodeGen/builtins-arm64.c +++ b/clang/test/CodeGen/builtins-arm64.c @@ -58,6 +58,12 @@ void prefetch() { // CHECK: call {{.*}} @llvm.prefetch(i8* null, i32 0, i32 3, i32 0) } +int32_t jcvt(double v) { + //CHECK-LABEL: @jcvt( + //CHECK: call i32 @llvm.aarch64.fjcvtzs + return __builtin_arm_jcvt(v); +} + __typeof__(__builtin_arm_rsr("1:2:3:4:5")) rsr(void); uint32_t rsr() { diff --git a/clang/test/CodeGen/builtins-wasm.c b/clang/test/CodeGen/builtins-wasm.c index 4784d6ff86ebdb..8a17fb39641b3e 100644 --- a/clang/test/CodeGen/builtins-wasm.c +++ b/clang/test/CodeGen/builtins-wasm.c @@ -38,6 +38,12 @@ void data_drop() { // WEBASSEMBLY64: call void @llvm.wasm.data.drop(i32 3) } +__SIZE_TYPE__ tls_size() { + return __builtin_wasm_tls_size(); + // WEBASSEMBLY32: call i32 @llvm.wasm.tls.size.i32() + // WEBASSEMBLY64: call i64 @llvm.wasm.tls.size.i64() +} + void throw(void *obj) { return __builtin_wasm_throw(0, obj); // WEBASSEMBLY32: call void @llvm.wasm.throw(i32 0, i8* %{{.*}}) diff --git a/clang/test/CodeGen/memtag-attr.cpp b/clang/test/CodeGen/memtag-attr.cpp new file mode 100644 index 00000000000000..f0b0785367ba9a --- /dev/null +++ b/clang/test/CodeGen/memtag-attr.cpp @@ -0,0 +1,19 @@ +// Make sure the sanitize_memtag attribute is emitted when using MemTag sanitizer. +// Make sure __attribute__((no_sanitize("memtag")) disables instrumentation. + +// RUN: %clang_cc1 -triple aarch64-unknown-linux -disable-O0-optnone \ +// RUN: -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NO %s + +// RUN: %clang_cc1 -triple aarch64-unknown-linux -fsanitize=memtag \ +// RUN: -disable-O0-optnone -emit-llvm -o - %s | \ +// RUN: FileCheck -check-prefix=CHECK-MEMTAG %s + +int HasSanitizeMemTag() { return 1; } +// CHECK-NO: {{Function Attrs: noinline nounwind$}} +// CHECK-MEMTAG: Function Attrs: noinline nounwind sanitize_memtag + +__attribute__((no_sanitize("memtag"))) int NoSanitizeQuoteAddress() { + return 0; +} +// CHECK-NO: {{Function Attrs: noinline nounwind$}} +// CHECK-MEMTAG: {{Function Attrs: noinline nounwind$}} diff --git a/clang/test/CodeGen/ppc-mm-malloc-le.c b/clang/test/CodeGen/ppc-mm-malloc-le.c index 7f9c4c9d524481..ba888afcd194f8 100644 --- a/clang/test/CodeGen/ppc-mm-malloc-le.c +++ b/clang/test/CodeGen/ppc-mm-malloc-le.c @@ -24,30 +24,14 @@ test_mm_malloc() { // CHECK: store i64 [[REG1]], i64* [[REG4:[0-9a-zA-Z_%.]+]], align 8 // CHECK-NEXT: store i64 [[REG2]], i64* [[REG5:[0-9a-zA-Z_%.]+]], align 8 // CHECK-NEXT: store i64 16, i64* [[REG6:[0-9a-zA-Z_%.]+]], align 8 -// CHECK-NEXT: store i64 16, i64* [[REG7:[0-9a-zA-Z_%.]+]], align 8 // CHECK-NEXT: [[REG8:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG5]], align 8 -// CHECK-NEXT: [[REG9:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG7]], align 8 -// CHECK-NEXT: [[REG10:[0-9a-zA-Z_%.]+]] = icmp eq i64 [[REG8]], [[REG9]] -// CHECK-NEXT: br i1 [[REG10]], label %[[REG11:[0-9a-zA-Z_%.]+]], label %[[REG12:[0-9a-zA-Z_%.]+]] -// CHECK: [[REG11]]: -// CHECK-NEXT: [[REG13:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG5]], align 8 -// CHECK-NEXT: [[REG14:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG6]], align 8 -// CHECK-NEXT: [[REG15:[0-9a-zA-Z_%.]+]] = icmp eq i64 [[REG13]], [[REG14]] -// CHECK-NEXT: br i1 [[REG15]], label %[[REG16:[0-9a-zA-Z_%.]+]], label %[[REG12:[0-9a-zA-Z_%.]+]] -// CHECK: [[REG16]]: -// CHECK-NEXT: [[REG17:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG4]], align 8 -// CHECK-NEXT: [[REG18:[0-9a-zA-Z_%.]+]] = call noalias i8* @malloc(i64 [[REG17]]) -// CHECK-NEXT: store i8* [[REG18]], i8** [[REG3]], align 8 -// CHECK-NEXT: br label %[[REG19:[0-9a-zA-Z_%.]+]] -// CHECK: [[REG12]]: -// CHECK-NEXT: [[REG20:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG5]], align 8 -// CHECK-NEXT: [[REG21:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG6]], align 8 -// CHECK-NEXT: [[REG22:[0-9a-zA-Z_%.]+]] = icmp ult i64 [[REG20]], [[REG21]] -// CHECK-NEXT: br i1 [[REG22]], label %[[REG23:[0-9a-zA-Z_%.]+]], label %[[REG24:[0-9a-zA-Z_%.]+]] +// CHECK-NEXT: [[REG9:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG6]], align 8 +// CHECK-NEXT: [[REG10:[0-9a-zA-Z_%.]+]] = icmp ult i64 [[REG8]], [[REG9]] +// CHECK-NEXT: br i1 [[REG10]], label %[[REG23:[0-9a-zA-Z_%.]+]], label %[[REG24:[0-9a-zA-Z_%.]+]] // CHECK: [[REG23]]: // CHECK-NEXT: [[REG25:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG6]], align 8 // CHECK-NEXT: store i64 [[REG25]], i64* [[REG5]], align 8 -// CHECK-NEXT: br label %[[REG12:[0-9a-zA-Z_%.]+]]4 +// CHECK-NEXT: br label %[[REG24:[0-9a-zA-Z_%.]+]] // CHECK: [[REG24]]: // CHECK-NEXT: [[REG26:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG5]], align 8 // CHECK-NEXT: [[REG27:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG4]], align 8 diff --git a/clang/test/CodeGen/ppc-mm-malloc.c b/clang/test/CodeGen/ppc-mm-malloc.c index 8559a850a89bca..6e8f6807b50bbc 100644 --- a/clang/test/CodeGen/ppc-mm-malloc.c +++ b/clang/test/CodeGen/ppc-mm-malloc.c @@ -24,30 +24,14 @@ test_mm_malloc() { // CHECK: store i64 [[REG1]], i64* [[REG4:[0-9a-zA-Z_%.]+]], align 8 // CHECK-NEXT: store i64 [[REG2]], i64* [[REG5:[0-9a-zA-Z_%.]+]], align 8 // CHECK-NEXT: store i64 16, i64* [[REG6:[0-9a-zA-Z_%.]+]], align 8 -// CHECK-NEXT: store i64 16, i64* [[REG7:[0-9a-zA-Z_%.]+]], align 8 // CHECK-NEXT: [[REG8:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG5]], align 8 -// CHECK-NEXT: [[REG9:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG7]], align 8 -// CHECK-NEXT: [[REG10:[0-9a-zA-Z_%.]+]] = icmp eq i64 [[REG8]], [[REG9]] -// CHECK-NEXT: br i1 [[REG10]], label %[[REG11:[0-9a-zA-Z_%.]+]], label %[[REG12:[0-9a-zA-Z_%.]+]] -// CHECK: [[REG11]]: -// CHECK-NEXT: [[REG13:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG5]], align 8 -// CHECK-NEXT: [[REG14:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG6]], align 8 -// CHECK-NEXT: [[REG15:[0-9a-zA-Z_%.]+]] = icmp eq i64 [[REG13]], [[REG14]] -// CHECK-NEXT: br i1 [[REG15]], label %[[REG16:[0-9a-zA-Z_%.]+]], label %[[REG12:[0-9a-zA-Z_%.]+]] -// CHECK: [[REG16]]: -// CHECK-NEXT: [[REG17:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG4]], align 8 -// CHECK-NEXT: [[REG18:[0-9a-zA-Z_%.]+]] = call noalias i8* @malloc(i64 [[REG17]]) -// CHECK-NEXT: store i8* [[REG18]], i8** [[REG3]], align 8 -// CHECK-NEXT: br label %[[REG19:[0-9a-zA-Z_%.]+]] -// CHECK: [[REG12]]: -// CHECK-NEXT: [[REG20:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG5]], align 8 -// CHECK-NEXT: [[REG21:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG6]], align 8 -// CHECK-NEXT: [[REG22:[0-9a-zA-Z_%.]+]] = icmp ult i64 [[REG20]], [[REG21]] -// CHECK-NEXT: br i1 [[REG22]], label %[[REG23:[0-9a-zA-Z_%.]+]], label %[[REG24:[0-9a-zA-Z_%.]+]] +// CHECK-NEXT: [[REG9:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG6]], align 8 +// CHECK-NEXT: [[REG10:[0-9a-zA-Z_%.]+]] = icmp ult i64 [[REG8]], [[REG9]] +// CHECK-NEXT: br i1 [[REG10]], label %[[REG23:[0-9a-zA-Z_%.]+]], label %[[REG24:[0-9a-zA-Z_%.]+]] // CHECK: [[REG23]]: // CHECK-NEXT: [[REG25:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG6]], align 8 // CHECK-NEXT: store i64 [[REG25]], i64* [[REG5]], align 8 -// CHECK-NEXT: br label %[[REG12:[0-9a-zA-Z_%.]+]]4 +// CHECK-NEXT: br label %[[REG24:[0-9a-zA-Z_%.]+]] // CHECK: [[REG24]]: // CHECK-NEXT: [[REG26:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG5]], align 8 // CHECK-NEXT: [[REG27:[0-9a-zA-Z_%.]+]] = load i64, i64* [[REG4]], align 8 diff --git a/clang/test/CodeGen/ppc64-long-double.cpp b/clang/test/CodeGen/ppc64-long-double.cpp index d588d6b80e9639..a35965f2bf6848 100644 --- a/clang/test/CodeGen/ppc64-long-double.cpp +++ b/clang/test/CodeGen/ppc64-long-double.cpp @@ -3,6 +3,14 @@ // RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm -o - %s -mlong-double-64 | \ // RUN: FileCheck --check-prefix=FP64 %s +// musl defaults to -mlong-double-64, so -mlong-double-128 is needed to make +// -mabi=ieeelongdouble effective. +// RUN: %clang_cc1 -triple powerpc64-linux-musl -emit-llvm -o - %s -mlong-double-128 \ +// RUN: -mabi=ieeelongdouble | FileCheck --check-prefix=FP128 %s +// RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm -o - %s \ +// RUN: -mabi=ieeelongdouble | FileCheck --check-prefix=FP128 %s + +// IBM extended double is the default. // RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm -o - %s | \ // RUN: FileCheck --check-prefix=IBM128 %s // RUN: %clang_cc1 -triple powerpc64-linux-musl -emit-llvm -o - -mlong-double-128 %s | \ @@ -13,10 +21,13 @@ int size = sizeof(x); // FP64: @x = global double {{.*}}, align 8 // FP64: @size = global i32 8 +// FP128: @x = global fp128 {{.*}}, align 16 +// FP128: @size = global i32 16 // IBM128: @x = global ppc_fp128 {{.*}}, align 16 // IBM128: @size = global i32 16 long double foo(long double d) { return d; } // FP64: double @_Z3fooe(double %d) +// FP128: fp128 @_Z3foou9__ieee128(fp128 %d) // IBM128: ppc_fp128 @_Z3foog(ppc_fp128 %d) diff --git a/clang/test/CodeGen/riscv32-ilp32-ilp32f-abi.c b/clang/test/CodeGen/riscv32-ilp32-ilp32f-abi.c index 0c2f0791e316b8..677040626f578d 100644 --- a/clang/test/CodeGen/riscv32-ilp32-ilp32f-abi.c +++ b/clang/test/CodeGen/riscv32-ilp32-ilp32f-abi.c @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -triple riscv32 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \ +// RUN: | FileCheck %s // This file contains test cases that will have the same output for the ilp32 // and ilp32f ABIs. @@ -35,8 +37,8 @@ int f_scalar_stack_1(int32_t a, int64_t b, int32_t c, double d, long double e, // the presence of large return values that consume a register due to the need // to pass a pointer. -// CHECK-LABEL: define void @f_scalar_stack_2(%struct.large* noalias sret %agg.result, i32 %a, i64 %b, i64 %c, fp128 %d, i8 zeroext %e, i8 %f, i8 %g) -struct large f_scalar_stack_2(int32_t a, int64_t b, int64_t c, long double d, +// CHECK-LABEL: define void @f_scalar_stack_2(%struct.large* noalias sret %agg.result, i32 %a, i64 %b, double %c, fp128 %d, i8 zeroext %e, i8 %f, i8 %g) +struct large f_scalar_stack_2(int32_t a, int64_t b, double c, long double d, uint8_t e, int8_t f, uint8_t g) { return (struct large){a, e, f, g}; } diff --git a/clang/test/CodeGen/riscv32-ilp32-ilp32f-ilp32d-abi.c b/clang/test/CodeGen/riscv32-ilp32-ilp32f-ilp32d-abi.c index 12837fce9422fb..fa11c1772d726e 100644 --- a/clang/test/CodeGen/riscv32-ilp32-ilp32f-ilp32d-abi.c +++ b/clang/test/CodeGen/riscv32-ilp32-ilp32f-ilp32d-abi.c @@ -1,6 +1,10 @@ // RUN: %clang_cc1 -triple riscv32 -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -triple riscv32 -emit-llvm -fforce-enable-int128 %s -o - \ // RUN: | FileCheck %s -check-prefixes=CHECK,CHECK-FORCEINT128 +// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \ +// RUN: | FileCheck %s // This file contains test cases that will have the same output for the ilp32, // ilp32f, and ilp32d ABIs. diff --git a/clang/test/CodeGen/riscv32-ilp32d-abi.c b/clang/test/CodeGen/riscv32-ilp32d-abi.c new file mode 100644 index 00000000000000..b10656cf123e4c --- /dev/null +++ b/clang/test/CodeGen/riscv32-ilp32d-abi.c @@ -0,0 +1,282 @@ +// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \ +// RUN: | FileCheck %s + +#include + +// Verify that the tracking of used GPRs and FPRs works correctly by checking +// that small integers are sign/zero extended when passed in registers. + +// Doubles are passed in FPRs, so argument 'i' will be passed zero-extended +// because it will be passed in a GPR. + +// CHECK: define void @f_fpr_tracking(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, i8 zeroext %i) +void f_fpr_tracking(double a, double b, double c, double d, double e, double f, + double g, double h, uint8_t i) {} + +// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will +// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are +// available the widths are <= XLEN and FLEN, and should be expanded to +// separate arguments in IR. They are passed by the same rules for returns, +// but will be lowered to simple two-element structs if necessary (as LLVM IR +// functions cannot return multiple values). + +// A struct containing just one floating-point real is passed as though it +// were a standalone floating-point real. + +struct double_s { double f; }; + +// CHECK: define void @f_double_s_arg(double) +void f_double_s_arg(struct double_s a) {} + +// CHECK: define double @f_ret_double_s() +struct double_s f_ret_double_s() { + return (struct double_s){1.0}; +} + +// A struct containing a double and any number of zero-width bitfields is +// passed as though it were a standalone floating-point real. + +struct zbf_double_s { int : 0; double f; }; +struct zbf_double_zbf_s { int : 0; double f; int : 0; }; + +// CHECK: define void @f_zbf_double_s_arg(double) +void f_zbf_double_s_arg(struct zbf_double_s a) {} + +// CHECK: define double @f_ret_zbf_double_s() +struct zbf_double_s f_ret_zbf_double_s() { + return (struct zbf_double_s){1.0}; +} + +// CHECK: define void @f_zbf_double_zbf_s_arg(double) +void f_zbf_double_zbf_s_arg(struct zbf_double_zbf_s a) {} + +// CHECK: define double @f_ret_zbf_double_zbf_s() +struct zbf_double_zbf_s f_ret_zbf_double_zbf_s() { + return (struct zbf_double_zbf_s){1.0}; +} + +// Check that structs containing two floating point values (FLEN <= width) are +// expanded provided sufficient FPRs are available. + +struct double_double_s { double f; double g; }; +struct double_float_s { double f; float g; }; + +// CHECK: define void @f_double_double_s_arg(double, double) +void f_double_double_s_arg(struct double_double_s a) {} + +// CHECK: define { double, double } @f_ret_double_double_s() +struct double_double_s f_ret_double_double_s() { + return (struct double_double_s){1.0, 2.0}; +} + +// CHECK: define void @f_double_float_s_arg(double, float) +void f_double_float_s_arg(struct double_float_s a) {} + +// CHECK: define { double, float } @f_ret_double_float_s() +struct double_float_s f_ret_double_float_s() { + return (struct double_float_s){1.0, 2.0}; +} + +// CHECK: define void @f_double_double_s_arg_insufficient_fprs(float %a, double %b, double %c, double %d, double %e, double %f, double %g, %struct.double_double_s* %h) +void f_double_double_s_arg_insufficient_fprs(float a, double b, double c, double d, + double e, double f, double g, struct double_double_s h) {} + +// Check that structs containing int+double values are expanded, provided +// sufficient FPRs and GPRs are available. The integer components are neither +// sign or zero-extended. + +struct double_int8_s { double f; int8_t i; }; +struct double_uint8_s { double f; uint8_t i; }; +struct double_int32_s { double f; int32_t i; }; +struct double_int64_s { double f; int64_t i; }; +struct double_int64bf_s { double f; int64_t i : 32; }; +struct double_int8_zbf_s { double f; int8_t i; int : 0; }; + +// CHECK: define void @f_double_int8_s_arg(double, i8) +void f_double_int8_s_arg(struct double_int8_s a) {} + +// CHECK: define { double, i8 } @f_ret_double_int8_s() +struct double_int8_s f_ret_double_int8_s() { + return (struct double_int8_s){1.0, 2}; +} + +// CHECK: define void @f_double_uint8_s_arg(double, i8) +void f_double_uint8_s_arg(struct double_uint8_s a) {} + +// CHECK: define { double, i8 } @f_ret_double_uint8_s() +struct double_uint8_s f_ret_double_uint8_s() { + return (struct double_uint8_s){1.0, 2}; +} + +// CHECK: define void @f_double_int32_s_arg(double, i32) +void f_double_int32_s_arg(struct double_int32_s a) {} + +// CHECK: define { double, i32 } @f_ret_double_int32_s() +struct double_int32_s f_ret_double_int32_s() { + return (struct double_int32_s){1.0, 2}; +} + +// CHECK: define void @f_double_int64_s_arg(%struct.double_int64_s* %a) +void f_double_int64_s_arg(struct double_int64_s a) {} + +// CHECK: define void @f_ret_double_int64_s(%struct.double_int64_s* noalias sret %agg.result) +struct double_int64_s f_ret_double_int64_s() { + return (struct double_int64_s){1.0, 2}; +} + +// CHECK: define void @f_double_int64bf_s_arg(double, i32) +void f_double_int64bf_s_arg(struct double_int64bf_s a) {} + +// CHECK: define { double, i32 } @f_ret_double_int64bf_s() +struct double_int64bf_s f_ret_double_int64bf_s() { + return (struct double_int64bf_s){1.0, 2}; +} + +// The zero-width bitfield means the struct can't be passed according to the +// floating point calling convention. + +// CHECK: define void @f_double_int8_zbf_s(double, i8) +void f_double_int8_zbf_s(struct double_int8_zbf_s a) {} + +// CHECK: define { double, i8 } @f_ret_double_int8_zbf_s() +struct double_int8_zbf_s f_ret_double_int8_zbf_s() { + return (struct double_int8_zbf_s){1.0, 2}; +} + +// CHECK: define void @f_double_int8_s_arg_insufficient_gprs(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, %struct.double_int8_s* %i) +void f_double_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e, + int f, int g, int h, struct double_int8_s i) {} + +// CHECK: define void @f_struct_double_int8_insufficient_fprs(float %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, %struct.double_int8_s* %i) +void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double d, + double e, double f, double g, double h, struct double_int8_s i) {} + +// Complex floating-point values or structs containing a single complex +// floating-point value should be passed as if it were an fp+fp struct. + +// CHECK: define void @f_doublecomplex(double %a.coerce0, double %a.coerce1) +void f_doublecomplex(double __complex__ a) {} + +// CHECK: define { double, double } @f_ret_doublecomplex() +double __complex__ f_ret_doublecomplex() { + return 1.0; +} + +struct doublecomplex_s { double __complex__ c; }; + +// CHECK: define void @f_doublecomplex_s_arg(double, double) +void f_doublecomplex_s_arg(struct doublecomplex_s a) {} + +// CHECK: define { double, double } @f_ret_doublecomplex_s() +struct doublecomplex_s f_ret_doublecomplex_s() { + return (struct doublecomplex_s){1.0}; +} + +// Test single or two-element structs that need flattening. e.g. those +// containing nested structs, doubles in small arrays, zero-length structs etc. + +struct doublearr1_s { double a[1]; }; + +// CHECK: define void @f_doublearr1_s_arg(double) +void f_doublearr1_s_arg(struct doublearr1_s a) {} + +// CHECK: define double @f_ret_doublearr1_s() +struct doublearr1_s f_ret_doublearr1_s() { + return (struct doublearr1_s){{1.0}}; +} + +struct doublearr2_s { double a[2]; }; + +// CHECK: define void @f_doublearr2_s_arg(double, double) +void f_doublearr2_s_arg(struct doublearr2_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_s() +struct doublearr2_s f_ret_doublearr2_s() { + return (struct doublearr2_s){{1.0, 2.0}}; +} + +struct doublearr2_tricky1_s { struct { double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky1_s_arg(double, double) +void f_doublearr2_tricky1_s_arg(struct doublearr2_tricky1_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky1_s() +struct doublearr2_tricky1_s f_ret_doublearr2_tricky1_s() { + return (struct doublearr2_tricky1_s){{{{1.0}}, {{2.0}}}}; +} + +struct doublearr2_tricky2_s { struct {}; struct { double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky2_s_arg(double, double) +void f_doublearr2_tricky2_s_arg(struct doublearr2_tricky2_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky2_s() +struct doublearr2_tricky2_s f_ret_doublearr2_tricky2_s() { + return (struct doublearr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct doublearr2_tricky3_s { union {}; struct { double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky3_s_arg(double, double) +void f_doublearr2_tricky3_s_arg(struct doublearr2_tricky3_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky3_s() +struct doublearr2_tricky3_s f_ret_doublearr2_tricky3_s() { + return (struct doublearr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct doublearr2_tricky4_s { union {}; struct { struct {}; double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky4_s_arg(double, double) +void f_doublearr2_tricky4_s_arg(struct doublearr2_tricky4_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky4_s() +struct doublearr2_tricky4_s f_ret_doublearr2_tricky4_s() { + return (struct doublearr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}}; +} + +// Test structs that should be passed according to the normal integer calling +// convention. + +struct int_double_int_s { int a; double b; int c; }; + +// CHECK: define void @f_int_double_int_s_arg(%struct.int_double_int_s* %a) +void f_int_double_int_s_arg(struct int_double_int_s a) {} + +// CHECK: define void @f_ret_int_double_int_s(%struct.int_double_int_s* noalias sret %agg.result) +struct int_double_int_s f_ret_int_double_int_s() { + return (struct int_double_int_s){1, 2.0, 3}; +} + +struct int64_double_s { int64_t a; double b; }; + +// CHECK: define void @f_int64_double_s_arg(%struct.int64_double_s* %a) +void f_int64_double_s_arg(struct int64_double_s a) {} + +// CHECK: define void @f_ret_int64_double_s(%struct.int64_double_s* noalias sret %agg.result) +struct int64_double_s f_ret_int64_double_s() { + return (struct int64_double_s){1, 2.0}; +} + +struct char_char_double_s { char a; char b; double c; }; + +// CHECK-LABEL: define void @f_char_char_double_s_arg(%struct.char_char_double_s* %a) +void f_char_char_double_s_arg(struct char_char_double_s a) {} + +// CHECK: define void @f_ret_char_char_double_s(%struct.char_char_double_s* noalias sret %agg.result) +struct char_char_double_s f_ret_char_char_double_s() { + return (struct char_char_double_s){1, 2, 3.0}; +} + +// Unions are always passed according to the integer calling convention, even +// if they can only contain a double. + +union double_u { double a; }; + +// CHECK: define void @f_double_u_arg(i64 %a.coerce) +void f_double_u_arg(union double_u a) {} + +// CHECK: define i64 @f_ret_double_u() +union double_u f_ret_double_u() { + return (union double_u){1.0}; +} diff --git a/clang/test/CodeGen/riscv32-ilp32f-abi.c b/clang/test/CodeGen/riscv32-ilp32f-abi.c new file mode 100644 index 00000000000000..76092958aeddff --- /dev/null +++ b/clang/test/CodeGen/riscv32-ilp32f-abi.c @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \ +// RUN: | FileCheck %s + +#include + +// Doubles are still passed in GPRs, so the 'e' argument will be anyext as +// GPRs are exhausted. + +// CHECK: define void @f_fpr_tracking(double %a, double %b, double %c, double %d, i8 %e) +void f_fpr_tracking(double a, double b, double c, double d, int8_t e) {} + +// Lowering for doubles is unnmodified, as 64 > FLEN. + +struct double_s { double d; }; + +// CHECK: define void @f_double_s_arg(i64 %a.coerce) +void f_double_s_arg(struct double_s a) {} + +// CHECK: define i64 @f_ret_double_s() +struct double_s f_ret_double_s() { + return (struct double_s){1.0}; +} + +struct double_double_s { double d; double e; }; + +// CHECK: define void @f_double_double_s_arg(%struct.double_double_s* %a) +void f_double_double_s_arg(struct double_double_s a) {} + +// CHECK: define void @f_ret_double_double_s(%struct.double_double_s* noalias sret %agg.result) +struct double_double_s f_ret_double_double_s() { + return (struct double_double_s){1.0, 2.0}; +} + +struct double_int8_s { double d; int64_t i; }; + +struct int_double_s { int a; double b; }; + +// CHECK: define void @f_int_double_s_arg(%struct.int_double_s* %a) +void f_int_double_s_arg(struct int_double_s a) {} + +// CHECK: define void @f_ret_int_double_s(%struct.int_double_s* noalias sret %agg.result) +struct int_double_s f_ret_int_double_s() { + return (struct int_double_s){1, 2.0}; +} + diff --git a/clang/test/CodeGen/riscv32-ilp32f-ilp32d-abi.c b/clang/test/CodeGen/riscv32-ilp32f-ilp32d-abi.c new file mode 100644 index 00000000000000..b960513655b114 --- /dev/null +++ b/clang/test/CodeGen/riscv32-ilp32f-ilp32d-abi.c @@ -0,0 +1,275 @@ +// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \ +// RUN: | FileCheck %s + +#include + +// Verify that the tracking of used GPRs and FPRs works correctly by checking +// that small integers are sign/zero extended when passed in registers. + +// Floats are passed in FPRs, so argument 'i' will be passed zero-extended +// because it will be passed in a GPR. + +// CHECK: define void @f_fpr_tracking(float %a, float %b, float %c, float %d, float %e, float %f, float %g, float %h, i8 zeroext %i) +void f_fpr_tracking(float a, float b, float c, float d, float e, float f, + float g, float h, uint8_t i) {} + +// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will +// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are +// available the widths are <= XLEN and FLEN, and should be expanded to +// separate arguments in IR. They are passed by the same rules for returns, +// but will be lowered to simple two-element structs if necessary (as LLVM IR +// functions cannot return multiple values). + +// A struct containing just one floating-point real is passed as though it +// were a standalone floating-point real. + +struct float_s { float f; }; + +// CHECK: define void @f_float_s_arg(float) +void f_float_s_arg(struct float_s a) {} + +// CHECK: define float @f_ret_float_s() +struct float_s f_ret_float_s() { + return (struct float_s){1.0}; +} + +// A struct containing a float and any number of zero-width bitfields is +// passed as though it were a standalone floating-point real. + +struct zbf_float_s { int : 0; float f; }; +struct zbf_float_zbf_s { int : 0; float f; int : 0; }; + +// CHECK: define void @f_zbf_float_s_arg(float) +void f_zbf_float_s_arg(struct zbf_float_s a) {} + +// CHECK: define float @f_ret_zbf_float_s() +struct zbf_float_s f_ret_zbf_float_s() { + return (struct zbf_float_s){1.0}; +} + +// CHECK: define void @f_zbf_float_zbf_s_arg(float) +void f_zbf_float_zbf_s_arg(struct zbf_float_zbf_s a) {} + +// CHECK: define float @f_ret_zbf_float_zbf_s() +struct zbf_float_zbf_s f_ret_zbf_float_zbf_s() { + return (struct zbf_float_zbf_s){1.0}; +} + +// Check that structs containing two float values (FLEN <= width) are expanded +// provided sufficient FPRs are available. + +struct float_float_s { float f; float g; }; + +// CHECK: define void @f_float_float_s_arg(float, float) +void f_float_float_s_arg(struct float_float_s a) {} + +// CHECK: define { float, float } @f_ret_float_float_s() +struct float_float_s f_ret_float_float_s() { + return (struct float_float_s){1.0, 2.0}; +} + +// CHECK: define void @f_float_float_s_arg_insufficient_fprs(float %a, float %b, float %c, float %d, float %e, float %f, float %g, [2 x i32] %h.coerce) +void f_float_float_s_arg_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, struct float_float_s h) {} + +// Check that structs containing int+float values are expanded, provided +// sufficient FPRs and GPRs are available. The integer components are neither +// sign or zero-extended. + +struct float_int8_s { float f; int8_t i; }; +struct float_uint8_s { float f; uint8_t i; }; +struct float_int32_s { float f; int32_t i; }; +struct float_int64_s { float f; int64_t i; }; +struct float_int64bf_s { float f; int64_t i : 32; }; +struct float_int8_zbf_s { float f; int8_t i; int : 0; }; + +// CHECK: define void @f_float_int8_s_arg(float, i8) +void f_float_int8_s_arg(struct float_int8_s a) {} + +// CHECK: define { float, i8 } @f_ret_float_int8_s() +struct float_int8_s f_ret_float_int8_s() { + return (struct float_int8_s){1.0, 2}; +} + +// CHECK: define void @f_float_uint8_s_arg(float, i8) +void f_float_uint8_s_arg(struct float_uint8_s a) {} + +// CHECK: define { float, i8 } @f_ret_float_uint8_s() +struct float_uint8_s f_ret_float_uint8_s() { + return (struct float_uint8_s){1.0, 2}; +} + +// CHECK: define void @f_float_int32_s_arg(float, i32) +void f_float_int32_s_arg(struct float_int32_s a) {} + +// CHECK: define { float, i32 } @f_ret_float_int32_s() +struct float_int32_s f_ret_float_int32_s() { + return (struct float_int32_s){1.0, 2}; +} + +// CHECK: define void @f_float_int64_s_arg(%struct.float_int64_s* %a) +void f_float_int64_s_arg(struct float_int64_s a) {} + +// CHECK: define void @f_ret_float_int64_s(%struct.float_int64_s* noalias sret %agg.result) +struct float_int64_s f_ret_float_int64_s() { + return (struct float_int64_s){1.0, 2}; +} + +// CHECK: define void @f_float_int64bf_s_arg(float, i32) +void f_float_int64bf_s_arg(struct float_int64bf_s a) {} + +// CHECK: define { float, i32 } @f_ret_float_int64bf_s() +struct float_int64bf_s f_ret_float_int64bf_s() { + return (struct float_int64bf_s){1.0, 2}; +} + +// The zero-width bitfield means the struct can't be passed according to the +// floating point calling convention. + +// CHECK: define void @f_float_int8_zbf_s(float, i8) +void f_float_int8_zbf_s(struct float_int8_zbf_s a) {} + +// CHECK: define { float, i8 } @f_ret_float_int8_zbf_s() +struct float_int8_zbf_s f_ret_float_int8_zbf_s() { + return (struct float_int8_zbf_s){1.0, 2}; +} + +// CHECK: define void @f_float_int8_s_arg_insufficient_gprs(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, [2 x i32] %i.coerce) +void f_float_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e, + int f, int g, int h, struct float_int8_s i) {} + +// CHECK: define void @f_struct_float_int8_insufficient_fprs(float %a, float %b, float %c, float %d, float %e, float %f, float %g, float %h, [2 x i32] %i.coerce) +void f_struct_float_int8_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, float h, struct float_int8_s i) {} + +// Complex floating-point values or structs containing a single complex +// floating-point value should be passed as if it were an fp+fp struct. + +// CHECK: define void @f_floatcomplex(float %a.coerce0, float %a.coerce1) +void f_floatcomplex(float __complex__ a) {} + +// CHECK: define { float, float } @f_ret_floatcomplex() +float __complex__ f_ret_floatcomplex() { + return 1.0; +} + +struct floatcomplex_s { float __complex__ c; }; + +// CHECK: define void @f_floatcomplex_s_arg(float, float) +void f_floatcomplex_s_arg(struct floatcomplex_s a) {} + +// CHECK: define { float, float } @f_ret_floatcomplex_s() +struct floatcomplex_s f_ret_floatcomplex_s() { + return (struct floatcomplex_s){1.0}; +} + +// Test single or two-element structs that need flattening. e.g. those +// containing nested structs, floats in small arrays, zero-length structs etc. + +struct floatarr1_s { float a[1]; }; + +// CHECK: define void @f_floatarr1_s_arg(float) +void f_floatarr1_s_arg(struct floatarr1_s a) {} + +// CHECK: define float @f_ret_floatarr1_s() +struct floatarr1_s f_ret_floatarr1_s() { + return (struct floatarr1_s){{1.0}}; +} + +struct floatarr2_s { float a[2]; }; + +// CHECK: define void @f_floatarr2_s_arg(float, float) +void f_floatarr2_s_arg(struct floatarr2_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_s() +struct floatarr2_s f_ret_floatarr2_s() { + return (struct floatarr2_s){{1.0, 2.0}}; +} + +struct floatarr2_tricky1_s { struct { float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky1_s_arg(float, float) +void f_floatarr2_tricky1_s_arg(struct floatarr2_tricky1_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky1_s() +struct floatarr2_tricky1_s f_ret_floatarr2_tricky1_s() { + return (struct floatarr2_tricky1_s){{{{1.0}}, {{2.0}}}}; +} + +struct floatarr2_tricky2_s { struct {}; struct { float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky2_s_arg(float, float) +void f_floatarr2_tricky2_s_arg(struct floatarr2_tricky2_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky2_s() +struct floatarr2_tricky2_s f_ret_floatarr2_tricky2_s() { + return (struct floatarr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct floatarr2_tricky3_s { union {}; struct { float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky3_s_arg(float, float) +void f_floatarr2_tricky3_s_arg(struct floatarr2_tricky3_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky3_s() +struct floatarr2_tricky3_s f_ret_floatarr2_tricky3_s() { + return (struct floatarr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct floatarr2_tricky4_s { union {}; struct { struct {}; float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky4_s_arg(float, float) +void f_floatarr2_tricky4_s_arg(struct floatarr2_tricky4_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky4_s() +struct floatarr2_tricky4_s f_ret_floatarr2_tricky4_s() { + return (struct floatarr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}}; +} + +// Test structs that should be passed according to the normal integer calling +// convention. + +struct int_float_int_s { int a; float b; int c; }; + +// CHECK: define void @f_int_float_int_s_arg(%struct.int_float_int_s* %a) +void f_int_float_int_s_arg(struct int_float_int_s a) {} + +// CHECK: define void @f_ret_int_float_int_s(%struct.int_float_int_s* noalias sret %agg.result) +struct int_float_int_s f_ret_int_float_int_s() { + return (struct int_float_int_s){1, 2.0, 3}; +} + +struct int64_float_s { int64_t a; float b; }; + +// CHECK: define void @f_int64_float_s_arg(%struct.int64_float_s* %a) +void f_int64_float_s_arg(struct int64_float_s a) {} + +// CHECK: define void @f_ret_int64_float_s(%struct.int64_float_s* noalias sret %agg.result) +struct int64_float_s f_ret_int64_float_s() { + return (struct int64_float_s){1, 2.0}; +} + +struct char_char_float_s { char a; char b; float c; }; + +// CHECK-LABEL: define void @f_char_char_float_s_arg([2 x i32] %a.coerce) +void f_char_char_float_s_arg(struct char_char_float_s a) {} + +// CHECK: define [2 x i32] @f_ret_char_char_float_s() +struct char_char_float_s f_ret_char_char_float_s() { + return (struct char_char_float_s){1, 2, 3.0}; +} + +// Unions are always passed according to the integer calling convention, even +// if they can only contain a float. + +union float_u { float a; }; + +// CHECK: define void @f_float_u_arg(i32 %a.coerce) +void f_float_u_arg(union float_u a) {} + +// CHECK: define i32 @f_ret_float_u() +union float_u f_ret_float_u() { + return (union float_u){1.0}; +} diff --git a/clang/test/CodeGen/riscv64-lp64-lp64f-abi.c b/clang/test/CodeGen/riscv64-lp64-lp64f-abi.c index 3b944e716a2a04..d457bdf3c64e3a 100644 --- a/clang/test/CodeGen/riscv64-lp64-lp64f-abi.c +++ b/clang/test/CodeGen/riscv64-lp64-lp64f-abi.c @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -triple riscv64 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \ +// RUN: | FileCheck %s // This file contains test cases that will have the same output for the lp64 // and lp64f ABIs. diff --git a/clang/test/CodeGen/riscv64-lp64-lp64f-lp64d-abi.c b/clang/test/CodeGen/riscv64-lp64-lp64f-lp64d-abi.c index f51d8252b8f47a..f3523702e9a29e 100644 --- a/clang/test/CodeGen/riscv64-lp64-lp64f-lp64d-abi.c +++ b/clang/test/CodeGen/riscv64-lp64-lp64f-lp64d-abi.c @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -triple riscv64 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +d -target-abi lp64d -emit-llvm %s -o - \ +// RUN: | FileCheck %s // This file contains test cases that will have the same output for the lp64, // lp64f, and lp64d ABIs. diff --git a/clang/test/CodeGen/riscv64-lp64d-abi.c b/clang/test/CodeGen/riscv64-lp64d-abi.c new file mode 100644 index 00000000000000..00967b5fca852b --- /dev/null +++ b/clang/test/CodeGen/riscv64-lp64d-abi.c @@ -0,0 +1,272 @@ +// RUN: %clang_cc1 -triple riscv64 -target-feature +d -target-abi lp64d -emit-llvm %s -o - \ +// RUN: | FileCheck %s + +#include + +// Verify that the tracking of used GPRs and FPRs works correctly by checking +// that small integers are sign/zero extended when passed in registers. + +// Doubles are passed in FPRs, so argument 'i' will be passed zero-extended +// because it will be passed in a GPR. + +// CHECK: define void @f_fpr_tracking(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, i8 zeroext %i) +void f_fpr_tracking(double a, double b, double c, double d, double e, double f, + double g, double h, uint8_t i) {} + +// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will +// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are +// available the widths are <= XLEN and FLEN, and should be expanded to +// separate arguments in IR. They are passed by the same rules for returns, +// but will be lowered to simple two-element structs if necessary (as LLVM IR +// functions cannot return multiple values). + +// A struct containing just one floating-point real is passed as though it +// were a standalone floating-point real. + +struct double_s { double f; }; + +// CHECK: define void @f_double_s_arg(double) +void f_double_s_arg(struct double_s a) {} + +// CHECK: define double @f_ret_double_s() +struct double_s f_ret_double_s() { + return (struct double_s){1.0}; +} + +// A struct containing a double and any number of zero-width bitfields is +// passed as though it were a standalone floating-point real. + +struct zbf_double_s { int : 0; double f; }; +struct zbf_double_zbf_s { int : 0; double f; int : 0; }; + +// CHECK: define void @f_zbf_double_s_arg(double) +void f_zbf_double_s_arg(struct zbf_double_s a) {} + +// CHECK: define double @f_ret_zbf_double_s() +struct zbf_double_s f_ret_zbf_double_s() { + return (struct zbf_double_s){1.0}; +} + +// CHECK: define void @f_zbf_double_zbf_s_arg(double) +void f_zbf_double_zbf_s_arg(struct zbf_double_zbf_s a) {} + +// CHECK: define double @f_ret_zbf_double_zbf_s() +struct zbf_double_zbf_s f_ret_zbf_double_zbf_s() { + return (struct zbf_double_zbf_s){1.0}; +} + +// Check that structs containing two floating point values (FLEN <= width) are +// expanded provided sufficient FPRs are available. + +struct double_double_s { double f; double g; }; +struct double_float_s { double f; float g; }; + +// CHECK: define void @f_double_double_s_arg(double, double) +void f_double_double_s_arg(struct double_double_s a) {} + +// CHECK: define { double, double } @f_ret_double_double_s() +struct double_double_s f_ret_double_double_s() { + return (struct double_double_s){1.0, 2.0}; +} + +// CHECK: define void @f_double_float_s_arg(double, float) +void f_double_float_s_arg(struct double_float_s a) {} + +// CHECK: define { double, float } @f_ret_double_float_s() +struct double_float_s f_ret_double_float_s() { + return (struct double_float_s){1.0, 2.0}; +} + +// CHECK: define void @f_double_double_s_arg_insufficient_fprs(float %a, double %b, double %c, double %d, double %e, double %f, double %g, [2 x i64] %h.coerce) +void f_double_double_s_arg_insufficient_fprs(float a, double b, double c, double d, + double e, double f, double g, struct double_double_s h) {} + +// Check that structs containing int+double values are expanded, provided +// sufficient FPRs and GPRs are available. The integer components are neither +// sign or zero-extended. + +struct double_int8_s { double f; int8_t i; }; +struct double_uint8_s { double f; uint8_t i; }; +struct double_int32_s { double f; int32_t i; }; +struct double_int64_s { double f; int64_t i; }; +struct double_int128bf_s { double f; __int128_t i : 64; }; +struct double_int8_zbf_s { double f; int8_t i; int : 0; }; + +// CHECK: define void @f_double_int8_s_arg(double, i8) +void f_double_int8_s_arg(struct double_int8_s a) {} + +// CHECK: define { double, i8 } @f_ret_double_int8_s() +struct double_int8_s f_ret_double_int8_s() { + return (struct double_int8_s){1.0, 2}; +} + +// CHECK: define void @f_double_uint8_s_arg(double, i8) +void f_double_uint8_s_arg(struct double_uint8_s a) {} + +// CHECK: define { double, i8 } @f_ret_double_uint8_s() +struct double_uint8_s f_ret_double_uint8_s() { + return (struct double_uint8_s){1.0, 2}; +} + +// CHECK: define void @f_double_int32_s_arg(double, i32) +void f_double_int32_s_arg(struct double_int32_s a) {} + +// CHECK: define { double, i32 } @f_ret_double_int32_s() +struct double_int32_s f_ret_double_int32_s() { + return (struct double_int32_s){1.0, 2}; +} + +// CHECK: define void @f_double_int64_s_arg(double, i64) +void f_double_int64_s_arg(struct double_int64_s a) {} + +// CHECK: define { double, i64 } @f_ret_double_int64_s() +struct double_int64_s f_ret_double_int64_s() { + return (struct double_int64_s){1.0, 2}; +} + +// CHECK: define void @f_double_int128bf_s_arg(double, i64) +void f_double_int128bf_s_arg(struct double_int128bf_s a) {} + +// CHECK: define { double, i64 } @f_ret_double_int128bf_s() +struct double_int128bf_s f_ret_double_int128bf_s() { + return (struct double_int128bf_s){1.0, 2}; +} + +// The zero-width bitfield means the struct can't be passed according to the +// floating point calling convention. + +// CHECK: define void @f_double_int8_zbf_s(double, i8) +void f_double_int8_zbf_s(struct double_int8_zbf_s a) {} + +// CHECK: define { double, i8 } @f_ret_double_int8_zbf_s() +struct double_int8_zbf_s f_ret_double_int8_zbf_s() { + return (struct double_int8_zbf_s){1.0, 2}; +} + +// CHECK: define void @f_double_int8_s_arg_insufficient_gprs(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e, i32 signext %f, i32 signext %g, i32 signext %h, [2 x i64] %i.coerce) +void f_double_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e, + int f, int g, int h, struct double_int8_s i) {} + +// CHECK: define void @f_struct_double_int8_insufficient_fprs(float %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, [2 x i64] %i.coerce) +void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double d, + double e, double f, double g, double h, struct double_int8_s i) {} + +// Complex floating-point values or structs containing a single complex +// floating-point value should be passed as if it were an fp+fp struct. + +// CHECK: define void @f_doublecomplex(double %a.coerce0, double %a.coerce1) +void f_doublecomplex(double __complex__ a) {} + +// CHECK: define { double, double } @f_ret_doublecomplex() +double __complex__ f_ret_doublecomplex() { + return 1.0; +} + +struct doublecomplex_s { double __complex__ c; }; + +// CHECK: define void @f_doublecomplex_s_arg(double, double) +void f_doublecomplex_s_arg(struct doublecomplex_s a) {} + +// CHECK: define { double, double } @f_ret_doublecomplex_s() +struct doublecomplex_s f_ret_doublecomplex_s() { + return (struct doublecomplex_s){1.0}; +} + +// Test single or two-element structs that need flattening. e.g. those +// containing nested structs, doubles in small arrays, zero-length structs etc. + +struct doublearr1_s { double a[1]; }; + +// CHECK: define void @f_doublearr1_s_arg(double) +void f_doublearr1_s_arg(struct doublearr1_s a) {} + +// CHECK: define double @f_ret_doublearr1_s() +struct doublearr1_s f_ret_doublearr1_s() { + return (struct doublearr1_s){{1.0}}; +} + +struct doublearr2_s { double a[2]; }; + +// CHECK: define void @f_doublearr2_s_arg(double, double) +void f_doublearr2_s_arg(struct doublearr2_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_s() +struct doublearr2_s f_ret_doublearr2_s() { + return (struct doublearr2_s){{1.0, 2.0}}; +} + +struct doublearr2_tricky1_s { struct { double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky1_s_arg(double, double) +void f_doublearr2_tricky1_s_arg(struct doublearr2_tricky1_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky1_s() +struct doublearr2_tricky1_s f_ret_doublearr2_tricky1_s() { + return (struct doublearr2_tricky1_s){{{{1.0}}, {{2.0}}}}; +} + +struct doublearr2_tricky2_s { struct {}; struct { double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky2_s_arg(double, double) +void f_doublearr2_tricky2_s_arg(struct doublearr2_tricky2_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky2_s() +struct doublearr2_tricky2_s f_ret_doublearr2_tricky2_s() { + return (struct doublearr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct doublearr2_tricky3_s { union {}; struct { double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky3_s_arg(double, double) +void f_doublearr2_tricky3_s_arg(struct doublearr2_tricky3_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky3_s() +struct doublearr2_tricky3_s f_ret_doublearr2_tricky3_s() { + return (struct doublearr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct doublearr2_tricky4_s { union {}; struct { struct {}; double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky4_s_arg(double, double) +void f_doublearr2_tricky4_s_arg(struct doublearr2_tricky4_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky4_s() +struct doublearr2_tricky4_s f_ret_doublearr2_tricky4_s() { + return (struct doublearr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}}; +} + +// Test structs that should be passed according to the normal integer calling +// convention. + +struct int_double_int_s { int a; double b; int c; }; + +// CHECK: define void @f_int_double_int_s_arg(%struct.int_double_int_s* %a) +void f_int_double_int_s_arg(struct int_double_int_s a) {} + +// CHECK: define void @f_ret_int_double_int_s(%struct.int_double_int_s* noalias sret %agg.result) +struct int_double_int_s f_ret_int_double_int_s() { + return (struct int_double_int_s){1, 2.0, 3}; +} + +struct char_char_double_s { char a; char b; double c; }; + +// CHECK-LABEL: define void @f_char_char_double_s_arg([2 x i64] %a.coerce) +void f_char_char_double_s_arg(struct char_char_double_s a) {} + +// CHECK: define [2 x i64] @f_ret_char_char_double_s() +struct char_char_double_s f_ret_char_char_double_s() { + return (struct char_char_double_s){1, 2, 3.0}; +} + +// Unions are always passed according to the integer calling convention, even +// if they can only contain a double. + +union double_u { double a; }; + +// CHECK: define void @f_double_u_arg(i64 %a.coerce) +void f_double_u_arg(union double_u a) {} + +// CHECK: define i64 @f_ret_double_u() +union double_u f_ret_double_u() { + return (union double_u){1.0}; +} diff --git a/clang/test/CodeGen/riscv64-lp64f-lp64d-abi.c b/clang/test/CodeGen/riscv64-lp64f-lp64d-abi.c new file mode 100644 index 00000000000000..eee2bc1bdcc6fb --- /dev/null +++ b/clang/test/CodeGen/riscv64-lp64f-lp64d-abi.c @@ -0,0 +1,265 @@ +// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +d -target-abi lp64d -emit-llvm %s -o - \ +// RUN: | FileCheck %s + +#include + +// Verify that the tracking of used GPRs and FPRs works correctly by checking +// that small integers are sign/zero extended when passed in registers. + +// Floats are passed in FPRs, so argument 'i' will be passed zero-extended +// because it will be passed in a GPR. + +// CHECK: define void @f_fpr_tracking(float %a, float %b, float %c, float %d, float %e, float %f, float %g, float %h, i8 zeroext %i) +void f_fpr_tracking(float a, float b, float c, float d, float e, float f, + float g, float h, uint8_t i) {} + +// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will +// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are +// available the widths are <= XLEN and FLEN, and should be expanded to +// separate arguments in IR. They are passed by the same rules for returns, +// but will be lowered to simple two-element structs if necessary (as LLVM IR +// functions cannot return multiple values). + +// A struct containing just one floating-point real is passed as though it +// were a standalone floating-point real. + +struct float_s { float f; }; + +// CHECK: define void @f_float_s_arg(float) +void f_float_s_arg(struct float_s a) {} + +// CHECK: define float @f_ret_float_s() +struct float_s f_ret_float_s() { + return (struct float_s){1.0}; +} + +// A struct containing a float and any number of zero-width bitfields is +// passed as though it were a standalone floating-point real. + +struct zbf_float_s { int : 0; float f; }; +struct zbf_float_zbf_s { int : 0; float f; int : 0; }; + +// CHECK: define void @f_zbf_float_s_arg(float) +void f_zbf_float_s_arg(struct zbf_float_s a) {} + +// CHECK: define float @f_ret_zbf_float_s() +struct zbf_float_s f_ret_zbf_float_s() { + return (struct zbf_float_s){1.0}; +} + +// CHECK: define void @f_zbf_float_zbf_s_arg(float) +void f_zbf_float_zbf_s_arg(struct zbf_float_zbf_s a) {} + +// CHECK: define float @f_ret_zbf_float_zbf_s() +struct zbf_float_zbf_s f_ret_zbf_float_zbf_s() { + return (struct zbf_float_zbf_s){1.0}; +} + +// Check that structs containing two float values (FLEN <= width) are expanded +// provided sufficient FPRs are available. + +struct float_float_s { float f; float g; }; + +// CHECK: define void @f_float_float_s_arg(float, float) +void f_float_float_s_arg(struct float_float_s a) {} + +// CHECK: define { float, float } @f_ret_float_float_s() +struct float_float_s f_ret_float_float_s() { + return (struct float_float_s){1.0, 2.0}; +} + +// CHECK: define void @f_float_float_s_arg_insufficient_fprs(float %a, float %b, float %c, float %d, float %e, float %f, float %g, i64 %h.coerce) +void f_float_float_s_arg_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, struct float_float_s h) {} + +// Check that structs containing int+float values are expanded, provided +// sufficient FPRs and GPRs are available. The integer components are neither +// sign or zero-extended. + +struct float_int8_s { float f; int8_t i; }; +struct float_uint8_s { float f; uint8_t i; }; +struct float_int32_s { float f; int32_t i; }; +struct float_int64_s { float f; int64_t i; }; +struct float_int128bf_s { float f; __int128_t i : 64; }; +struct float_int8_zbf_s { float f; int8_t i; int : 0; }; + +// CHECK: define void @f_float_int8_s_arg(float, i8) +void f_float_int8_s_arg(struct float_int8_s a) {} + +// CHECK: define { float, i8 } @f_ret_float_int8_s() +struct float_int8_s f_ret_float_int8_s() { + return (struct float_int8_s){1.0, 2}; +} + +// CHECK: define void @f_float_uint8_s_arg(float, i8) +void f_float_uint8_s_arg(struct float_uint8_s a) {} + +// CHECK: define { float, i8 } @f_ret_float_uint8_s() +struct float_uint8_s f_ret_float_uint8_s() { + return (struct float_uint8_s){1.0, 2}; +} + +// CHECK: define void @f_float_int32_s_arg(float, i32) +void f_float_int32_s_arg(struct float_int32_s a) {} + +// CHECK: define { float, i32 } @f_ret_float_int32_s() +struct float_int32_s f_ret_float_int32_s() { + return (struct float_int32_s){1.0, 2}; +} + +// CHECK: define void @f_float_int64_s_arg(float, i64) +void f_float_int64_s_arg(struct float_int64_s a) {} + +// CHECK: define { float, i64 } @f_ret_float_int64_s() +struct float_int64_s f_ret_float_int64_s() { + return (struct float_int64_s){1.0, 2}; +} + +// CHECK: define void @f_float_int128bf_s_arg(float, i64) +void f_float_int128bf_s_arg(struct float_int128bf_s a) {} + +// CHECK: define <{ float, i64 }> @f_ret_float_int128bf_s() +struct float_int128bf_s f_ret_float_int128bf_s() { + return (struct float_int128bf_s){1.0, 2}; +} + +// The zero-width bitfield means the struct can't be passed according to the +// floating point calling convention. + +// CHECK: define void @f_float_int8_zbf_s(float, i8) +void f_float_int8_zbf_s(struct float_int8_zbf_s a) {} + +// CHECK: define { float, i8 } @f_ret_float_int8_zbf_s() +struct float_int8_zbf_s f_ret_float_int8_zbf_s() { + return (struct float_int8_zbf_s){1.0, 2}; +} + +// CHECK: define void @f_float_int8_s_arg_insufficient_gprs(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e, i32 signext %f, i32 signext %g, i32 signext %h, i64 %i.coerce) +void f_float_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e, + int f, int g, int h, struct float_int8_s i) {} + +// CHECK: define void @f_struct_float_int8_insufficient_fprs(float %a, float %b, float %c, float %d, float %e, float %f, float %g, float %h, i64 %i.coerce) +void f_struct_float_int8_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, float h, struct float_int8_s i) {} + +// Complex floating-point values or structs containing a single complex +// floating-point value should be passed as if it were an fp+fp struct. + +// CHECK: define void @f_floatcomplex(float %a.coerce0, float %a.coerce1) +void f_floatcomplex(float __complex__ a) {} + +// CHECK: define { float, float } @f_ret_floatcomplex() +float __complex__ f_ret_floatcomplex() { + return 1.0; +} + +struct floatcomplex_s { float __complex__ c; }; + +// CHECK: define void @f_floatcomplex_s_arg(float, float) +void f_floatcomplex_s_arg(struct floatcomplex_s a) {} + +// CHECK: define { float, float } @f_ret_floatcomplex_s() +struct floatcomplex_s f_ret_floatcomplex_s() { + return (struct floatcomplex_s){1.0}; +} + +// Test single or two-element structs that need flattening. e.g. those +// containing nested structs, floats in small arrays, zero-length structs etc. + +struct floatarr1_s { float a[1]; }; + +// CHECK: define void @f_floatarr1_s_arg(float) +void f_floatarr1_s_arg(struct floatarr1_s a) {} + +// CHECK: define float @f_ret_floatarr1_s() +struct floatarr1_s f_ret_floatarr1_s() { + return (struct floatarr1_s){{1.0}}; +} + +struct floatarr2_s { float a[2]; }; + +// CHECK: define void @f_floatarr2_s_arg(float, float) +void f_floatarr2_s_arg(struct floatarr2_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_s() +struct floatarr2_s f_ret_floatarr2_s() { + return (struct floatarr2_s){{1.0, 2.0}}; +} + +struct floatarr2_tricky1_s { struct { float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky1_s_arg(float, float) +void f_floatarr2_tricky1_s_arg(struct floatarr2_tricky1_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky1_s() +struct floatarr2_tricky1_s f_ret_floatarr2_tricky1_s() { + return (struct floatarr2_tricky1_s){{{{1.0}}, {{2.0}}}}; +} + +struct floatarr2_tricky2_s { struct {}; struct { float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky2_s_arg(float, float) +void f_floatarr2_tricky2_s_arg(struct floatarr2_tricky2_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky2_s() +struct floatarr2_tricky2_s f_ret_floatarr2_tricky2_s() { + return (struct floatarr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct floatarr2_tricky3_s { union {}; struct { float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky3_s_arg(float, float) +void f_floatarr2_tricky3_s_arg(struct floatarr2_tricky3_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky3_s() +struct floatarr2_tricky3_s f_ret_floatarr2_tricky3_s() { + return (struct floatarr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct floatarr2_tricky4_s { union {}; struct { struct {}; float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky4_s_arg(float, float) +void f_floatarr2_tricky4_s_arg(struct floatarr2_tricky4_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky4_s() +struct floatarr2_tricky4_s f_ret_floatarr2_tricky4_s() { + return (struct floatarr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}}; +} + +// Test structs that should be passed according to the normal integer calling +// convention. + +struct int_float_int_s { int a; float b; int c; }; + +// CHECK: define void @f_int_float_int_s_arg([2 x i64] %a.coerce) +void f_int_float_int_s_arg(struct int_float_int_s a) {} + +// CHECK: define [2 x i64] @f_ret_int_float_int_s() +struct int_float_int_s f_ret_int_float_int_s() { + return (struct int_float_int_s){1, 2.0, 3}; +} + +struct char_char_float_s { char a; char b; float c; }; + +// CHECK-LABEL: define void @f_char_char_float_s_arg(i64 %a.coerce) +void f_char_char_float_s_arg(struct char_char_float_s a) {} + +// CHECK: define i64 @f_ret_char_char_float_s() +struct char_char_float_s f_ret_char_char_float_s() { + return (struct char_char_float_s){1, 2, 3.0}; +} + +// Unions are always passed according to the integer calling convention, even +// if they can only contain a float. + +union float_u { float a; }; + +// CHECK: define void @f_float_u_arg(i64 %a.coerce) +void f_float_u_arg(union float_u a) {} + +// CHECK: define i64 @f_ret_float_u() +union float_u f_ret_float_u() { + return (union float_u){1.0}; +} diff --git a/clang/test/CodeGen/sancov-new-pm.c b/clang/test/CodeGen/sancov-new-pm.c deleted file mode 100644 index 06d9042bc70a8f..00000000000000 --- a/clang/test/CodeGen/sancov-new-pm.c +++ /dev/null @@ -1,41 +0,0 @@ -// Test that SanitizerCoverage works under the new pass manager. -// RUN: %clang -target x86_64-linux-gnu -fsanitize=fuzzer %s -fexperimental-new-pass-manager -S -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-O0 -// RUN: %clang -target x86_64-linux-gnu -fsanitize=fuzzer %s -fexperimental-new-pass-manager -O2 -S -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-O2 -// RUN: %clang -target x86_64-linux-gnu -fsanitize=fuzzer %s -fexperimental-new-pass-manager -flto -S -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-O0 -// RUN: %clang -target x86_64-linux-gnu -fsanitize=fuzzer %s -fexperimental-new-pass-manager -flto -O2 -S -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-O2 -// RUN: %clang -target x86_64-linux-gnu -fsanitize=fuzzer %s -fexperimental-new-pass-manager -flto=thin -S -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-O0 -// RUN: %clang -target x86_64-linux-gnu -fsanitize=fuzzer %s -fexperimental-new-pass-manager -flto=thin -O2 -S -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-O2,CHECK-O2-THINLTO - -extern void *memcpy(void *, const void *, unsigned long); -extern int printf(const char *restrict, ...); - -int LLVMFuzzerTestOneInput(const unsigned char *data, unsigned long size) { - unsigned char buf[4]; - - if (size < 8) - return 0; - - if (data[0] == 'h' && data[1] == 'i' && data[2] == '!') { - memcpy(buf, data, size); - printf("test: %.2X\n", buf[0]); - } - - return 0; -} - -// CHECK-DAG: declare void @__sanitizer_cov_pcs_init(i64*, i64*) -// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_pc_indir(i64) -// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_cmp1(i8 zeroext, i8 zeroext) -// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_cmp2(i16 zeroext, i16 zeroext) -// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_cmp4(i32 zeroext, i32 zeroext) -// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_cmp8(i64, i64) -// CHECK-O2-THINLTO-NOT: declare void @__sanitizer_cov_trace_const_cmp1(i8 zeroext, i8 zeroext) -// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_const_cmp2(i16 zeroext, i16 zeroext) -// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_const_cmp4(i32 zeroext, i32 zeroext) -// CHECK-O2-THINLTO-NOT: declare void @__sanitizer_cov_trace_const_cmp8(i64, i64) -// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_div4(i32 zeroext) -// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_div8(i64) -// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_gep(i64) -// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_switch(i64, i64*) -// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_pc() -// CHECK-O0-DAG: declare void @__sanitizer_cov_trace_pc_guard(i32*) diff --git a/clang/test/CodeGen/ubsan-function.cpp b/clang/test/CodeGen/ubsan-function.cpp new file mode 100644 index 00000000000000..749e6214242cf0 --- /dev/null +++ b/clang/test/CodeGen/ubsan-function.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s -fsanitize=function -fno-sanitize-recover=all | FileCheck %s + +// CHECK-LABEL: define void @_Z3funv() #0 prologue <{ i32, i32 }> <{ i32 846595819, i32 trunc (i64 sub (i64 ptrtoint (i8** @0 to i64), i64 ptrtoint (void ()* @_Z3funv to i64)) to i32) }> { +void fun() {} + +// CHECK-LABEL: define void @_Z6callerPFvvE(void ()* %f) +// CHECK: getelementptr <{ i32, i32 }>, <{ i32, i32 }>* {{.*}}, i32 0, i32 0, !nosanitize +// CHECK: load i32, i32* {{.*}}, align {{.*}}, !nosanitize +// CHECK: icmp eq i32 {{.*}}, 846595819, !nosanitize +// CHECK: br i1 {{.*}}, label %[[LABEL1:.*]], label %[[LABEL4:.*]], !nosanitize +// CHECK: [[LABEL1]]: +// CHECK: getelementptr <{ i32, i32 }>, <{ i32, i32 }>* {{.*}}, i32 0, i32 1, !nosanitize +// CHECK: load i32, i32* {{.*}}, align {{.*}}, !nosanitize +// CHECK: icmp eq i8* {{.*}}, bitcast ({ i8*, i8* }* @_ZTIFvvE to i8*), !nosanitize +// CHECK: br i1 {{.*}}, label %[[LABEL3:.*]], label %[[LABEL2:[^,]*]], {{.*}}!nosanitize +// CHECK: [[LABEL2]]: +// CHECK: call void @__ubsan_handle_function_type_mismatch_v1_abort(i8* {{.*}}, i64 {{.*}}, i64 {{.*}}, i64 {{.*}}) #{{.*}}, !nosanitize +// CHECK-NOT: unreachable +// CHECK: br label %[[LABEL3]], !nosanitize +// CHECK: [[LABEL3]]: +// CHECK: br label %[[LABEL4]], !nosanitize +void caller(void (*f)()) { f(); } diff --git a/clang/test/CodeGenObjC/Inputs/strong_in_union.h b/clang/test/CodeGenObjC/Inputs/strong_in_union.h deleted file mode 100644 index abe4549055c601..00000000000000 --- a/clang/test/CodeGenObjC/Inputs/strong_in_union.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef STRONG_IN_UNION_H -#define STRONG_IN_UNION_H -#pragma clang system_header - -typedef union { - id f0; - int *f1; -} U; - -#endif // STRONG_IN_UNION_H diff --git a/clang/test/CodeGenObjC/strong-in-c-struct.m b/clang/test/CodeGenObjC/strong-in-c-struct.m index 19cc1037c4cad8..8eeee4af0d30a1 100644 --- a/clang/test/CodeGenObjC/strong-in-c-struct.m +++ b/clang/test/CodeGenObjC/strong-in-c-struct.m @@ -1,11 +1,10 @@ -// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - -DUSESTRUCT -I %S/Inputs %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - -DUSESTRUCT %s | FileCheck %s -// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-pch -I %S/Inputs -o %t %s -// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -include-pch %t -emit-llvm -o - -DUSESTRUCT -I %S/Inputs %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-pch -o %t %s +// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -include-pch %t -emit-llvm -o - -DUSESTRUCT %s | FileCheck %s #ifndef HEADER #define HEADER -#include "strong_in_union.h" typedef void (^BlockTy)(void); @@ -695,14 +694,6 @@ void test_copy_constructor_Bitfield1(Bitfield1 *a) { Bitfield1 t = *a; } -// CHECK: define void @test_strong_in_union() -// CHECK: alloca %{{.*}} -// CHECK-NEXT: ret void - -void test_strong_in_union() { - U t; -} - // CHECK: define void @test_copy_constructor_VolatileArray( // CHECK: call void @__copy_constructor_8_8_s0_AB8s4n16_tv64w32_AE( diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx10.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx10.cl new file mode 100644 index 00000000000000..3921cb90c3a578 --- /dev/null +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx10.cl @@ -0,0 +1,24 @@ +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1010 -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1011 -S -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1012 -S -emit-llvm -o - %s | FileCheck %s + +typedef unsigned int uint; + +// CHECK-LABEL: @test_permlane16( +// CHECK: call i32 @llvm.amdgcn.permlane16(i32 %a, i32 %b, i32 %c, i32 %d, i1 true, i1 true) +void test_permlane16(global uint* out, uint a, uint b, uint c, uint d) { + *out = __builtin_amdgcn_permlane16(a, b, c, d, 1, 1); +} + +// CHECK-LABEL: @test_permlanex16( +// CHECK: call i32 @llvm.amdgcn.permlanex16(i32 %a, i32 %b, i32 %c, i32 %d, i1 true, i1 true) +void test_permlanex16(global uint* out, uint a, uint b, uint c, uint d) { + *out = __builtin_amdgcn_permlanex16(a, b, c, d, 1, 1); +} + +// CHECK-LABEL: @test_mov_dpp8( +// CHECK: call i32 @llvm.amdgcn.mov.dpp8.i32(i32 %a, i32 1) +void test_mov_dpp8(global uint* out, uint a) { + *out = __builtin_amdgcn_mov_dpp8(a, 1); +} diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl index e4c40d92266fde..bbae5ea24be0a7 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl @@ -5,6 +5,10 @@ typedef unsigned long ulong; typedef unsigned int uint; +typedef unsigned short ushort; +typedef half __attribute__((ext_vector_type(2))) half2; +typedef short __attribute__((ext_vector_type(2))) short2; +typedef ushort __attribute__((ext_vector_type(2))) ushort2; // CHECK-LABEL: @test_div_scale_f64 // CHECK: call { double, i1 } @llvm.amdgcn.div.scale.f64(double %a, double %b, i1 true) @@ -590,6 +594,66 @@ kernel void test_mbcnt_hi(global uint* out, uint src0, uint src1) { *out = __builtin_amdgcn_mbcnt_hi(src0, src1); } +// CHECK-LABEL: @test_alignbit( +// CHECK: tail call i32 @llvm.amdgcn.alignbit(i32 %src0, i32 %src1, i32 %src2) +kernel void test_alignbit(global uint* out, uint src0, uint src1, uint src2) { + *out = __builtin_amdgcn_alignbit(src0, src1, src2); +} + +// CHECK-LABEL: @test_alignbyte( +// CHECK: tail call i32 @llvm.amdgcn.alignbyte(i32 %src0, i32 %src1, i32 %src2) +kernel void test_alignbyte(global uint* out, uint src0, uint src1, uint src2) { + *out = __builtin_amdgcn_alignbyte(src0, src1, src2); +} + +// CHECK-LABEL: @test_ubfe( +// CHECK: tail call i32 @llvm.amdgcn.ubfe.i32(i32 %src0, i32 %src1, i32 %src2) +kernel void test_ubfe(global uint* out, uint src0, uint src1, uint src2) { + *out = __builtin_amdgcn_ubfe(src0, src1, src2); +} + +// CHECK-LABEL: @test_sbfe( +// CHECK: tail call i32 @llvm.amdgcn.sbfe.i32(i32 %src0, i32 %src1, i32 %src2) +kernel void test_sbfe(global uint* out, uint src0, uint src1, uint src2) { + *out = __builtin_amdgcn_sbfe(src0, src1, src2); +} + +// CHECK-LABEL: @test_cvt_pkrtz( +// CHECK: tail call <2 x half> @llvm.amdgcn.cvt.pkrtz(float %src0, float %src1) +kernel void test_cvt_pkrtz(global half2* out, float src0, float src1) { + *out = __builtin_amdgcn_cvt_pkrtz(src0, src1); +} + +// CHECK-LABEL: @test_cvt_pknorm_i16( +// CHECK: tail call <2 x i16> @llvm.amdgcn.cvt.pknorm.i16(float %src0, float %src1) +kernel void test_cvt_pknorm_i16(global short2* out, float src0, float src1) { + *out = __builtin_amdgcn_cvt_pknorm_i16(src0, src1); +} + +// CHECK-LABEL: @test_cvt_pknorm_u16( +// CHECK: tail call <2 x i16> @llvm.amdgcn.cvt.pknorm.u16(float %src0, float %src1) +kernel void test_cvt_pknorm_u16(global ushort2* out, float src0, float src1) { + *out = __builtin_amdgcn_cvt_pknorm_u16(src0, src1); +} + +// CHECK-LABEL: @test_cvt_pk_i16( +// CHECK: tail call <2 x i16> @llvm.amdgcn.cvt.pk.i16(i32 %src0, i32 %src1) +kernel void test_cvt_pk_i16(global short2* out, int src0, int src1) { + *out = __builtin_amdgcn_cvt_pk_i16(src0, src1); +} + +// CHECK-LABEL: @test_cvt_pk_u16( +// CHECK: tail call <2 x i16> @llvm.amdgcn.cvt.pk.u16(i32 %src0, i32 %src1) +kernel void test_cvt_pk_u16(global ushort2* out, uint src0, uint src1) { + *out = __builtin_amdgcn_cvt_pk_u16(src0, src1); +} + +// CHECK-LABEL: @test_cvt_pk_u8_f32 +// CHECK: tail call i32 @llvm.amdgcn.cvt.pk.u8.f32(float %src0, i32 %src1, i32 %src2) +kernel void test_cvt_pk_u8_f32(global uint* out, float src0, uint src1, uint src2) { + *out = __builtin_amdgcn_cvt_pk_u8_f32(src0, src1, src2); +} + // CHECK-DAG: [[$WI_RANGE]] = !{i32 0, i32 1024} // CHECK-DAG: attributes #[[$NOUNWIND_READONLY:[0-9]+]] = { nounwind readonly } // CHECK-DAG: attributes #[[$READ_EXEC_ATTRS]] = { convergent } diff --git a/clang/test/CodeGenOpenCL/sampler.cl b/clang/test/CodeGenOpenCL/sampler.cl index 74b6d55d5d37ec..1ef1f538b2562e 100644 --- a/clang/test/CodeGenOpenCL/sampler.cl +++ b/clang/test/CodeGenOpenCL/sampler.cl @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -emit-llvm -triple spir-unknown-unknown -o - -O0 | FileCheck %s // RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -triple spir-unknown-unknown -o - -O0 | FileCheck %s +// RUN: %clang_cc1 %s -cl-std=c++ -emit-llvm -triple spir-unknown-unknown -o - -O0 | FileCheck %s // // This test covers 5 cases of sampler initialzation: // 1. function argument passing @@ -29,7 +30,7 @@ const sampler_t glb_smp_const = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORD int get_sampler_initializer(void); void fnc4smp(sampler_t s) {} -// CHECK: define spir_func void @fnc4smp(%opencl.sampler_t addrspace(2)* % +// CHECK: define spir_func void [[FUNCNAME:@.*fnc4smp.*]](%opencl.sampler_t addrspace(2)* % kernel void foo(sampler_t smp_par) { // CHECK-LABEL: define spir_kernel void @foo(%opencl.sampler_t addrspace(2)* %smp_par) @@ -45,32 +46,32 @@ kernel void foo(sampler_t smp_par) { fnc4smp(smp); // CHECK-NOT: call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 19) // CHECK: [[SAMP:%[0-9]+]] = load %opencl.sampler_t addrspace(2)*, %opencl.sampler_t addrspace(2)** [[smp_ptr]] - // CHECK: call spir_func void @fnc4smp(%opencl.sampler_t addrspace(2)* [[SAMP]]) + // CHECK: call spir_func void [[FUNCNAME]](%opencl.sampler_t addrspace(2)* [[SAMP]]) // Case 1b fnc4smp(smp); // CHECK-NOT: call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 19) // CHECK: [[SAMP:%[0-9]+]] = load %opencl.sampler_t addrspace(2)*, %opencl.sampler_t addrspace(2)** [[smp_ptr]] - // CHECK: call spir_func void @fnc4smp(%opencl.sampler_t addrspace(2)* [[SAMP]]) + // CHECK: call spir_func void [[FUNCNAME]](%opencl.sampler_t addrspace(2)* [[SAMP]]) // Case 1a/2a fnc4smp(glb_smp); // CHECK: [[SAMP:%[0-9]+]] = call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 35) - // CHECK: call spir_func void @fnc4smp(%opencl.sampler_t addrspace(2)* [[SAMP]]) + // CHECK: call spir_func void [[FUNCNAME]](%opencl.sampler_t addrspace(2)* [[SAMP]]) // Case 1a/2c fnc4smp(glb_smp_const); // CHECK: [[SAMP:%[0-9]+]] = call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 35) - // CHECK: call spir_func void @fnc4smp(%opencl.sampler_t addrspace(2)* [[SAMP]]) + // CHECK: call spir_func void [[FUNCNAME]](%opencl.sampler_t addrspace(2)* [[SAMP]]) // Case 1c fnc4smp(smp_par); // CHECK: [[SAMP:%[0-9]+]] = load %opencl.sampler_t addrspace(2)*, %opencl.sampler_t addrspace(2)** [[smp_par_ptr]] - // CHECK: call spir_func void @fnc4smp(%opencl.sampler_t addrspace(2)* [[SAMP]]) + // CHECK: call spir_func void [[FUNCNAME]](%opencl.sampler_t addrspace(2)* [[SAMP]]) fnc4smp(5); // CHECK: [[SAMP:%[0-9]+]] = call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 5) - // CHECK: call spir_func void @fnc4smp(%opencl.sampler_t addrspace(2)* [[SAMP]]) + // CHECK: call spir_func void [[FUNCNAME]](%opencl.sampler_t addrspace(2)* [[SAMP]]) const sampler_t const_smp = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR; fnc4smp(const_smp); @@ -78,12 +79,12 @@ kernel void foo(sampler_t smp_par) { // CHECK: store %opencl.sampler_t addrspace(2)* [[CONST_SAMP]], %opencl.sampler_t addrspace(2)** [[CONST_SMP_PTR:%[a-zA-Z0-9]+]] fnc4smp(const_smp); // CHECK: [[SAMP:%[0-9]+]] = load %opencl.sampler_t addrspace(2)*, %opencl.sampler_t addrspace(2)** [[CONST_SMP_PTR]] - // CHECK: call spir_func void @fnc4smp(%opencl.sampler_t addrspace(2)* [[SAMP]]) + // CHECK: call spir_func void [[FUNCNAME]](%opencl.sampler_t addrspace(2)* [[SAMP]]) constant sampler_t constant_smp = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR; fnc4smp(constant_smp); // CHECK: [[SAMP:%[0-9]+]] = call %opencl.sampler_t addrspace(2)* @__translate_sampler_initializer(i32 35) - // CHECK: call spir_func void @fnc4smp(%opencl.sampler_t addrspace(2)* [[SAMP]]) + // CHECK: call spir_func void [[FUNCNAME]](%opencl.sampler_t addrspace(2)* [[SAMP]]) // TODO: enable sampler initialization with non-constant integer. //const sampler_t const_smp_func_init = get_sampler_initializer(); diff --git a/clang/test/CodeGenOpenCLCXX/atexit.cl b/clang/test/CodeGenOpenCLCXX/atexit.cl new file mode 100644 index 00000000000000..b4571f96a1a250 --- /dev/null +++ b/clang/test/CodeGenOpenCLCXX/atexit.cl @@ -0,0 +1,11 @@ +//RUN: %clang_cc1 %s -triple spir -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s + +struct S { + ~S(){}; +}; +S s; + +//CHECK-LABEL: define internal void @__cxx_global_var_init() +//CHECK: call i32 @__cxa_atexit(void (i8*)* bitcast (void (%struct.S addrspace(4)*)* @_ZNU3AS41SD1Ev to void (i8*)*), i8* null, i8 addrspace(1)* @__dso_handle) + +//CHECK: declare i32 @__cxa_atexit(void (i8*)*, i8*, i8 addrspace(1)*) diff --git a/clang/test/Driver/Inputs/solaris_sparc_tree/usr/lib/ld.so.1 b/clang/test/Driver/Inputs/basic_fuchsia_tree/lib/aarch64-fuchsia/c++/asan+noexcept/libc++.so similarity index 100% rename from clang/test/Driver/Inputs/solaris_sparc_tree/usr/lib/ld.so.1 rename to clang/test/Driver/Inputs/basic_fuchsia_tree/lib/aarch64-fuchsia/c++/asan+noexcept/libc++.so diff --git a/clang/test/Driver/Inputs/solaris_sparc_tree/usr/lib/sparcv9/ld.so.1 b/clang/test/Driver/Inputs/basic_fuchsia_tree/lib/x86_64-fuchsia/c++/asan+noexcept/libc++.so similarity index 100% rename from clang/test/Driver/Inputs/solaris_sparc_tree/usr/lib/sparcv9/ld.so.1 rename to clang/test/Driver/Inputs/basic_fuchsia_tree/lib/x86_64-fuchsia/c++/asan+noexcept/libc++.so diff --git a/clang/test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/ld.so.1 b/clang/test/Driver/Inputs/solaris_x86_tree/usr/lib/amd64/ld.so.1 deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/clang/test/Driver/Inputs/solaris_x86_tree/usr/lib/ld.so.1 b/clang/test/Driver/Inputs/solaris_x86_tree/usr/lib/ld.so.1 deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/clang/test/Driver/cl-thinlto-backend.c b/clang/test/Driver/cl-thinlto-backend.c new file mode 100644 index 00000000000000..4697a994906ab8 --- /dev/null +++ b/clang/test/Driver/cl-thinlto-backend.c @@ -0,0 +1,9 @@ +// RUN: %clang_cl -c -flto=thin -Fo%t.obj -- %s +// RUN: llvm-lto2 run -thinlto-distributed-indexes -o %t.exe %t.obj + +// -fthinlto_index should be passed to cc1 +// RUN: %clang_cl -### -c -fthinlto-index=%t.thinlto.bc -Fo%t1.obj \ +// RUN: -- %t.obj 2>&1 | FileCheck %s + +// CHECK: -fthinlto-index= +// CHECK: "-x" "ir" diff --git a/clang/test/Driver/clang-translation.c b/clang/test/Driver/clang-translation.c index 0054535115aad6..766e7793826925 100644 --- a/clang/test/Driver/clang-translation.c +++ b/clang/test/Driver/clang-translation.c @@ -318,7 +318,7 @@ // ANDROID-X86_64: "-target-cpu" "x86-64" // ANDROID-X86_64: "-target-feature" "+sse4.2" // ANDROID-X86_64: "-target-feature" "+popcnt" -// ANDROID-X86_64: "-target-feature" "+mcx16" +// ANDROID-X86_64: "-target-feature" "+cx16" // RUN: %clang -target mips-linux-gnu -### -S %s 2>&1 | \ // RUN: FileCheck -check-prefix=MIPS %s diff --git a/clang/test/Driver/cxa-atexit.cpp b/clang/test/Driver/cxa-atexit.cpp index ae955ea5a7dfc9..336756dedcecdd 100644 --- a/clang/test/Driver/cxa-atexit.cpp +++ b/clang/test/Driver/cxa-atexit.cpp @@ -19,7 +19,7 @@ // RUN: %clang -### -target sparc-sun-solaris -c %s -o /dev/null 2>&1 | FileCheck %s -check-prefix CHECK-SOLARIS // CHECK-WINDOWS: "-fno-use-cxa-atexit" -// CHECK-SOLARIS: "-fno-use-cxa-atexit" +// CHECK-SOLARIS-NOT: "-fno-use-cxa-atexit" // CHECK-HEXAGON-NOT: "-fno-use-cxa-atexit" // CHECK-XCORE: "-fno-use-cxa-atexit" // CHECK-MTI: "-fno-use-cxa-atexit" diff --git a/clang/test/Driver/darwin-ld.c b/clang/test/Driver/darwin-ld.c index f01eeb4ea28e02..eb357a9819ffc9 100644 --- a/clang/test/Driver/darwin-ld.c +++ b/clang/test/Driver/darwin-ld.c @@ -5,9 +5,9 @@ // Make sure we run dsymutil on source input files. // RUN: %clang -target i386-apple-darwin9 -### -g %s -o BAR 2> %t.log -// RUN: grep '".*dsymutil" "-o" "BAR.dSYM" "BAR"' %t.log +// RUN: grep '".*dsymutil\(.exe\)\?" "-o" "BAR.dSYM" "BAR"' %t.log // RUN: %clang -target i386-apple-darwin9 -### -g -filelist FOO %s -o BAR 2> %t.log -// RUN: grep '".*dsymutil" "-o" "BAR.dSYM" "BAR"' %t.log +// RUN: grep '".*dsymutil\(.exe\)\?" "-o" "BAR.dSYM" "BAR"' %t.log // Check linker changes that came with new linkedit format. // RUN: touch %t.o diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index 187d4bfd4301e3..2896eda5aaa0f4 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -97,7 +97,7 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=vptr -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-TRAP-UNDEF // CHECK-VPTR-TRAP-UNDEF: error: invalid argument '-fsanitize=vptr' not allowed with '-fsanitize-trap=undefined' -// RUN: %clang -fsanitize=vptr -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-NO-RTTI +// RUN: %clang -target x86_64-linux-gnu -fsanitize=vptr -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-NO-RTTI // CHECK-VPTR-NO-RTTI: '-fsanitize=vptr' not allowed with '-fno-rtti' // RUN: %clang -fsanitize=undefined -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-NO-RTTI @@ -181,6 +181,16 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=hwaddress,address -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANHA-SANA // CHECK-SANHA-SANA: '-fsanitize=hwaddress' not allowed with '-fsanitize=address' +// RUN: %clang -target aarch64-linux-android -fsanitize=memtag,address -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANMT-SANA +// CHECK-SANMT-SANA: '-fsanitize=memtag' not allowed with '-fsanitize=address' + +// RUN: %clang -target aarch64-linux-android -fsanitize=memtag,hwaddress -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANMT-SANHA +// CHECK-SANMT-SANHA: '-fsanitize=memtag' not allowed with '-fsanitize=hwaddress' + +// RUN: %clang -target i386-linux-android -fsanitize=memtag -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANMT-BAD-ARCH +// RUN: %clang -target x86_64-linux-android -fsanitize=memtag -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANMT-BAD-ARCH +// CHECK-SANMT-BAD-ARCH: unsupported option '-fsanitize=memtag' for target + // RUN: %clang -target x86_64-linux-gnu -fsanitize=address -fsanitize-address-use-after-scope %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-USE-AFTER-SCOPE // RUN: %clang_cl --target=x86_64-windows -fsanitize=address -fsanitize-address-use-after-scope -### -- %s 2>&1 | FileCheck %s --check-prefix=CHECK-USE-AFTER-SCOPE // CHECK-USE-AFTER-SCOPE: -cc1{{.*}}-fsanitize-address-use-after-scope @@ -749,9 +759,12 @@ // CHECK-TSAN-MINIMAL: error: invalid argument '-fsanitize-minimal-runtime' not allowed with '-fsanitize=thread' // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-MINIMAL -// CHECK-UBSAN-MINIMAL: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute|function),?){18}"}} +// CHECK-UBSAN-MINIMAL: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){17}"}} // CHECK-UBSAN-MINIMAL: "-fsanitize-minimal-runtime" +// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize=function -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-FUNCTION-MINIMAL +// CHECK-UBSAN-FUNCTION-MINIMAL: error: invalid argument '-fsanitize=function' not allowed with '-fsanitize-minimal-runtime' + // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize=vptr -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-VPTR-MINIMAL // CHECK-UBSAN-VPTR-MINIMAL: error: invalid argument '-fsanitize=vptr' not allowed with '-fsanitize-minimal-runtime' diff --git a/clang/test/Driver/fuchsia.cpp b/clang/test/Driver/fuchsia.cpp index 823ded4b915441..a5297e76964e40 100644 --- a/clang/test/Driver/fuchsia.cpp +++ b/clang/test/Driver/fuchsia.cpp @@ -70,8 +70,9 @@ // RUN: -ccc-install-dir %S/Inputs/basic_fuchsia_tree/bin \ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: -fuse-ld=lld 2>&1\ -// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-ASAN-X86 +// RUN: | FileCheck %s -check-prefixes=CHECK-MULTILIB-X86,CHECK-MULTILIB-ASAN-NOEXCEPT-X86 // CHECK-MULTILIB-X86: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" // CHECK-MULTILIB-ASAN-X86: "-L{{.*}}{{/|\\\\}}..{{/|\\\\}}lib{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}c++{{/|\\\\}}asan" // CHECK-MULTILIB-NOEXCEPT-X86: "-L{{.*}}{{/|\\\\}}..{{/|\\\\}}lib{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}c++{{/|\\\\}}noexcept" +// CHECK-MULTILIB-ASAN-NOEXCEPT-X86: "-L{{.*}}{{/|\\\\}}..{{/|\\\\}}lib{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}c++{{/|\\\\}}asan+noexcept" // CHECK-MULTILIB-X86: "-L{{.*}}{{/|\\\\}}..{{/|\\\\}}lib{{/|\\\\}}x86_64-fuchsia{{/|\\\\}}c++" diff --git a/clang/test/Driver/ppc-abi.c b/clang/test/Driver/ppc-abi.c index a82a01de2781ec..fdcf45da2900dd 100644 --- a/clang/test/Driver/ppc-abi.c +++ b/clang/test/Driver/ppc-abi.c @@ -66,4 +66,22 @@ // CHECK-ELFv2-PIC: "-mrelocation-model" "pic" "-pic-level" "2" // CHECK-ELFv2-PIC: "-target-abi" "elfv2" +// Check -mabi=ieeelongdouble is passed through but it does not change -target-abi. +// RUN: %clang -target powerpc64le-linux-gnu %s -mabi=ieeelongdouble -mabi=elfv1 -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-ELFv1-IEEE %s +// RUN: %clang -target powerpc64le-linux-gnu %s -mabi=elfv1 -mabi=ieeelongdouble -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-ELFv1-IEEE %s +// RUN: %clang -target powerpc64le-linux-gnu %s -mabi=elfv2 -mabi=elfv1 -mabi=ibmlongdouble -mabi=ieeelongdouble -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-ELFv1-IEEE %s +// CHECK-ELFv1-IEEE: "-mabi=ieeelongdouble" +// CHECK-ELFv1-IEEE: "-target-abi" "elfv1" + +// Check -mabi=ibmlongdouble is the default. +// RUN: %clang -target powerpc64le-linux-gnu %s -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-ELFv2-IBM128 %s +// RUN: %clang -target powerpc64le-linux-gnu %s -mabi=ibmlongdouble -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-ELFv2-IBM128 %s + +// CHECK-ELFv2-IBM128-NOT: "-mabi=ieeelongdouble" +// CHECK-ELFv2-IBM128: "-target-abi" "elfv2" diff --git a/clang/test/Driver/riscv-abi.c b/clang/test/Driver/riscv-abi.c index 6a97ff671ddb07..1a4c7ed477b6d8 100644 --- a/clang/test/Driver/riscv-abi.c +++ b/clang/test/Driver/riscv-abi.c @@ -9,17 +9,15 @@ // CHECK-ILP32: "-target-abi" "ilp32" -// TODO: ilp32f support. -// RUN: not %clang -target riscv32-unknown-elf %s -o %t.o -mabi=ilp32f 2>&1 \ +// RUN: %clang -target riscv32-unknown-elf %s -### -o %t.o -march=rv32if -mabi=ilp32f 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-ILP32F %s -// CHECK-ILP32F: error: unknown target ABI 'ilp32f' +// CHECK-ILP32F: "-target-abi" "ilp32f" -// TODO: ilp32d support. -// RUN: not %clang -target riscv32-unknown-elf %s -o %t.o -mabi=ilp32d 2>&1 \ +// RUN: %clang -target riscv32-unknown-elf %s -### -o %t.o -march=rv32ifd -mabi=ilp32d 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-ILP32D %s -// CHECK-ILP32D: error: unknown target ABI 'ilp32d' +// CHECK-ILP32D: "-target-abi" "ilp32d" // RUN: not %clang -target riscv32-unknown-elf %s -o %t.o -mabi=lp64 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-RV32-LP64 %s @@ -37,17 +35,15 @@ // CHECK-LP64: "-target-abi" "lp64" -// TODO: lp64f support. -// RUN: not %clang -target riscv64-unknown-elf %s -o %t.o -mabi=lp64f 2>&1 \ +// RUN: %clang -target riscv64-unknown-elf %s -### -o %t.o -march=rv64f -mabi=lp64f 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-LP64F %s -// CHECK-LP64F: error: unknown target ABI 'lp64f' +// CHECK-LP64F: "-target-abi" "lp64f" -// TODO: lp64d support. -// RUN: not %clang -target riscv64-unknown-elf %s -o %t.o -mabi=lp64d 2>&1 \ +// RUN: %clang -target riscv64-unknown-elf %s -### -o %t.o -march=rv64d -mabi=lp64d 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-LP64D %s -// CHECK-LP64D: error: unknown target ABI 'lp64d' +// CHECK-LP64D: "-target-abi" "lp64d" // RUN: not %clang -target riscv64-unknown-elf %s -o %t.o -mabi=ilp32 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-RV64-ILP32 %s diff --git a/clang/test/Driver/solaris-ld.c b/clang/test/Driver/solaris-ld.c index 2fc5c91272aa03..59d03c4d822537 100644 --- a/clang/test/Driver/solaris-ld.c +++ b/clang/test/Driver/solaris-ld.c @@ -11,7 +11,6 @@ // CHECK-LD-SPARC32: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "sparc-sun-solaris2.11" // CHECK-LD-SPARC32-SAME: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-LD-SPARC32: "{{.*}}ld{{(.exe)?}}" -// CHECK-LD-SPARC32-SAME: "--dynamic-linker" "[[SYSROOT]]/usr/lib{{/|\\\\}}ld.so.1" // CHECK-LD-SPARC32-SAME: "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2{{/|\\\\}}crt1.o" // CHECK-LD-SPARC32-SAME: "[[SYSROOT]]/usr/lib{{/|\\\\}}crti.o" // CHECK-LD-SPARC32-SAME: "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2{{/|\\\\}}crtbegin.o" @@ -35,7 +34,6 @@ // CHECK-LD-SPARC64: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "sparcv9-sun-solaris2.11" // CHECK-LD-SPARC64-SAME: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-LD-SPARC64: "{{.*}}ld{{(.exe)?}}" -// CHECK-LD-SPARC64-SAME: "--dynamic-linker" "[[SYSROOT]]/usr/lib/sparcv9{{/|\\\\}}ld.so.1" // CHECK-LD-SPARC64-SAME: "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9{{/|\\\\}}crt1.o" // CHECK-LD-SPARC64-SAME: "[[SYSROOT]]/usr/lib/sparcv9{{/|\\\\}}crti.o" // CHECK-LD-SPARC64-SAME: "[[SYSROOT]]/usr/gcc/4.8/lib/gcc/sparc-sun-solaris2.11/4.8.2/sparcv9{{/|\\\\}}crtbegin.o" @@ -59,7 +57,6 @@ // CHECK-LD-X32: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "i386-pc-solaris2.11" // CHECK-LD-X32-SAME: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-LD-X32: "{{.*}}ld{{(.exe)?}}" -// CHECK-LD-X32-SAME: "--dynamic-linker" "[[SYSROOT]]/usr/lib{{/|\\\\}}ld.so.1" // CHECK-LD-X32-SAME: "[[SYSROOT]]/usr/lib{{/|\\\\}}crt1.o" // CHECK-LD-X32-SAME: "[[SYSROOT]]/usr/lib{{/|\\\\}}crti.o" // CHECK-LD-X32-SAME: "[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4{{/|\\\\}}crtbegin.o" @@ -83,7 +80,6 @@ // CHECK-LD-X64: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "x86_64-pc-solaris2.11" // CHECK-LD-X64-SAME: "-isysroot" "[[SYSROOT:[^"]+]]" // CHECK-LD-X64: "{{.*}}ld{{(.exe)?}}" -// CHECK-LD-X64-SAME: "--dynamic-linker" "[[SYSROOT]]/usr/lib/amd64{{/|\\\\}}ld.so.1" // CHECK-LD-X64-SAME: "[[SYSROOT]]/usr/lib/amd64{{/|\\\\}}crt1.o" // CHECK-LD-X64-SAME: "[[SYSROOT]]/usr/lib/amd64{{/|\\\\}}crti.o" // CHECK-LD-X64-SAME: "[[SYSROOT]]/usr/gcc/4.9/lib/gcc/i386-pc-solaris2.11/4.9.4/amd64{{/|\\\\}}crtbegin.o" diff --git a/clang/test/Driver/solaris-opts.c b/clang/test/Driver/solaris-opts.c index 8c54ae0a628d23..33d769efaa1798 100644 --- a/clang/test/Driver/solaris-opts.c +++ b/clang/test/Driver/solaris-opts.c @@ -1,4 +1,4 @@ // RUN: %clang %s --target=sparc-sun-solaris2.11 -### -o %t.o 2>&1 | FileCheck %s -// CHECK: "-fno-use-cxa-atexit" +// CHECK-NOT: "-fno-use-cxa-atexit" diff --git a/clang/test/Driver/thinlto_backend.c b/clang/test/Driver/thinlto_backend.c index b2b45f57088abb..7a3d6ede7c0da7 100644 --- a/clang/test/Driver/thinlto_backend.c +++ b/clang/test/Driver/thinlto_backend.c @@ -2,8 +2,14 @@ // RUN: llvm-lto -thinlto -o %t %t.o // -fthinlto_index should be passed to cc1 -// RUN: %clang -O2 -o %t1.o -x ir %t.o -c -fthinlto-index=%t.thinlto.bc -### 2>&1 | FileCheck %s -check-prefix=CHECK-THINLTOBE-ACTION +// RUN: %clang -O2 -o %t1.o -x ir %t.o -c -fthinlto-index=%t.thinlto.bc -### \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-THINLTOBE-ACTION // CHECK-THINLTOBE-ACTION: -fthinlto-index= +// CHECK-THINLTOBE-ACTION-SAME: {{"?-x"? "?ir"?}} + +// Check that this also works without -x ir. +// RUN: %clang -O2 -o %t1.o %t.o -c -fthinlto-index=%t.thinlto.bc -### 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-THINLTOBE-ACTION // -save-temps should be passed to cc1 // RUN: %clang -O2 -o %t1.o -x ir %t.o -c -fthinlto-index=%t.thinlto.bc -save-temps -### 2>&1 | FileCheck %s -check-prefix=CHECK-SAVE-TEMPS -check-prefix=CHECK-SAVE-TEMPS-CWD @@ -15,5 +21,6 @@ // CHECK-SAVE-TEMPS-NOT: -emit-llvm-bc // Ensure clang driver gives the expected error for incorrect input type -// RUN: not %clang -O2 -o %t1.o %s -c -fthinlto-index=%t.thinlto.bc 2>&1 | FileCheck %s -check-prefix=CHECK-WARNING -// CHECK-WARNING: error: invalid argument '-fthinlto-index={{.*}}' only allowed with '-x ir' +// RUN: not %clang -O2 -o %t1.o %s -c -fthinlto-index=%t.thinlto.bc 2>&1 \ +// RUN: | FileCheck %s -check-prefix=CHECK-WARNING +// CHECK-WARNING: error: option '-fthinlto-index={{.*}}' requires input to be LLVM bitcode diff --git a/clang/test/Driver/unknown-std.cl b/clang/test/Driver/unknown-std.cl index 90ee97b77f9cd0..285582ee0af6ad 100644 --- a/clang/test/Driver/unknown-std.cl +++ b/clang/test/Driver/unknown-std.cl @@ -10,7 +10,7 @@ // CHECK-NEXT: note: use 'cl1.1' for 'OpenCL 1.1' standard // CHECK-NEXT: note: use 'cl1.2' for 'OpenCL 1.2' standard // CHECK-NEXT: note: use 'cl2.0' for 'OpenCL 2.0' standard -// CHECK-NEXT: note: use 'c++' for 'OpenCL C++ 1.0' standard +// CHECK-NEXT: note: use 'c++' for 'C++ for OpenCL' standard // Make sure that no other output is present. // CHECK-NOT: {{^.+$}} diff --git a/clang/test/Frontend/macro_defined_type.cpp b/clang/test/Frontend/macro_defined_type.cpp index 7a4427e42c0992..d4f54b65a8d686 100644 --- a/clang/test/Frontend/macro_defined_type.cpp +++ b/clang/test/Frontend/macro_defined_type.cpp @@ -17,5 +17,5 @@ void Func() { // Added test for fix for P41835 #define _LIBCPP_FLOAT_ABI __attribute__((pcs("aapcs"))) struct A { - _LIBCPP_FLOAT_ABI int operator()() throw(); // expected-warning{{'pcs' calling convention ignored for this target}} + _LIBCPP_FLOAT_ABI int operator()() throw(); // expected-warning{{'pcs' calling convention is not supported for this target}} }; diff --git a/clang/test/Index/complete-exprs.c b/clang/test/Index/complete-exprs.c index 50f5025f1512f5..9beb16deef99b7 100644 --- a/clang/test/Index/complete-exprs.c +++ b/clang/test/Index/complete-exprs.c @@ -27,6 +27,7 @@ void f5(float f) { // RUN: c-index-test -code-completion-at=%s:7:10 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s // RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:10 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: NotImplemented:{TypedText __PRETTY_FUNCTION__} (65) +// CHECK-CC1: macro definition:{TypedText __VERSION__} (70) // CHECK-CC1: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (12) (unavailable) // CHECK-CC1-NOT: NotImplemented:{TypedText float} (65) // CHECK-CC1: ParmDecl:{ResultType int}{TypedText j} (8) @@ -38,6 +39,7 @@ void f5(float f) { // RUN: c-index-test -code-completion-at=%s:7:18 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s // RUN: c-index-test -code-completion-at=%s:7:22 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s // RUN: c-index-test -code-completion-at=%s:7:2 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC2 %s +// CHECK-CC2: macro definition:{TypedText __VERSION__} (70) // CHECK-CC2: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50) // CHECK-CC2: NotImplemented:{TypedText float} (50) // CHECK-CC2: ParmDecl:{ResultType int}{TypedText j} (34) diff --git a/clang/test/Index/complete-macros.c b/clang/test/Index/complete-macros.c index 394f93dea0e2b9..a0b1f4ae9e13da 100644 --- a/clang/test/Index/complete-macros.c +++ b/clang/test/Index/complete-macros.c @@ -28,7 +28,10 @@ void test_variadic() { // RUN: c-index-test -code-completion-at=%s:7:1 %s -I%S | FileCheck -check-prefix=CHECK-CC0 %s // CHECK-CC0-NOT: FOO // RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:1 %s -I%S | FileCheck -check-prefix=CHECK-CC1 %s +// (we had a regression that only occurred when parsing as C++, so check that too) +// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:7:1 -x c++ %s -I%S | FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: macro definition:{TypedText FOO} (70) +// CHECK-CC1: macro definition:{TypedText MACRO_IN_HEADER} (70) // RUN: c-index-test -code-completion-at=%s:13:13 %s -I%S | FileCheck -check-prefix=CHECK-CC2 %s // RUN: c-index-test -code-completion-at=%s:14:8 %s -I%S | FileCheck -check-prefix=CHECK-CC2 %s // RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:14:8 %s -I%S | FileCheck -check-prefix=CHECK-CC2 %s diff --git a/clang/test/Index/complete-macros.h b/clang/test/Index/complete-macros.h index 70f49e31a1e34c..c9ccba2cc0e986 100644 --- a/clang/test/Index/complete-macros.h +++ b/clang/test/Index/complete-macros.h @@ -2,5 +2,6 @@ #define COMPLETE_MACROS_H_GUARD void in_header(int); +#define MACRO_IN_HEADER 1 #endif diff --git a/clang/test/Lexer/has_feature_memtag_sanitizer.cpp b/clang/test/Lexer/has_feature_memtag_sanitizer.cpp new file mode 100644 index 00000000000000..64e55d7c23cf6c --- /dev/null +++ b/clang/test/Lexer/has_feature_memtag_sanitizer.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -E -fsanitize=memtag %s -o - | FileCheck --check-prefix=CHECK-MEMTAG %s +// RUN: %clang_cc1 -E %s -o - | FileCheck --check-prefix=CHECK-NO-MEMTAG %s + +#if __has_feature(memtag_sanitizer) +int MemTagSanitizerEnabled(); +#else +int MemTagSanitizerDisabled(); +#endif + +// CHECK-MEMTAG: MemTagSanitizerEnabled +// CHECK-NO-MEMTAG: MemTagSanitizerDisabled diff --git a/clang/test/OpenMP/cancel_if_messages.cpp b/clang/test/OpenMP/cancel_if_messages.cpp index 3d629c927e9072..222087ca9e61b8 100644 --- a/clang/test/OpenMP/cancel_if_messages.cpp +++ b/clang/test/OpenMP/cancel_if_messages.cpp @@ -9,6 +9,16 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp parallel + { +#pragma omp cancel parallel if (cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; + } +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/distribute_parallel_for_if_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_if_messages.cpp index a06ff2377c043a..e628a15c3ab44b 100644 --- a/clang/test/OpenMP/distribute_parallel_for_if_messages.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp distribute parallel for if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_if_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_if_messages.cpp index 7769272026e6b3..6cf18faf0a87fc 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_if_messages.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp distribute parallel for simd if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/for_loop_messages.cpp b/clang/test/OpenMP/for_loop_messages.cpp index 7c2663f61816f7..f5f6d0b703136e 100644 --- a/clang/test/OpenMP/for_loop_messages.cpp +++ b/clang/test/OpenMP/for_loop_messages.cpp @@ -626,6 +626,8 @@ template class TC { int ii, iii, kk; public: + enum { myconstant = 42 }; + int ub(); int dotest_lt(IT begin, IT end) { #pragma omp parallel // expected-error@+3 3 {{the loop initializer expression depends on the current loop control variable}} @@ -634,6 +636,12 @@ class TC { for (ii = ii * 10 + 25; ii < ii / ii - 23; ii += 1) ; +// Check that member function calls and enum constants in the condition is +// handled. +#pragma omp for + for (ii = 0; ii < ub() + this->myconstant; ii += 1) // expected-no-error + ; + #pragma omp parallel // expected-error@+4 2 {{expected loop invariant expression or ' * ii + ' kind of expression}} // expected-error@+3 {{expected loop invariant expression or ' * TC::ii + ' kind of expression}} diff --git a/clang/test/OpenMP/parallel_for_if_messages.cpp b/clang/test/OpenMP/parallel_for_if_messages.cpp index 32f9ef3a7defab..56bb06be0cc714 100644 --- a/clang/test/OpenMP/parallel_for_if_messages.cpp +++ b/clang/test/OpenMP/parallel_for_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp parallel for if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/parallel_for_simd_if_messages.cpp b/clang/test/OpenMP/parallel_for_simd_if_messages.cpp index aa1e302d042420..bab9339d491748 100644 --- a/clang/test/OpenMP/parallel_for_simd_if_messages.cpp +++ b/clang/test/OpenMP/parallel_for_simd_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp parallel for simd if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/parallel_if_messages.cpp b/clang/test/OpenMP/parallel_if_messages.cpp index 7f802a9e4236ab..f095e66bbfa5ed 100644 --- a/clang/test/OpenMP/parallel_if_messages.cpp +++ b/clang/test/OpenMP/parallel_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp parallel if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/parallel_sections_if_messages.cpp b/clang/test/OpenMP/parallel_sections_if_messages.cpp index 8d36b6d5d3086d..b7c92df4f30dff 100644 --- a/clang/test/OpenMP/parallel_sections_if_messages.cpp +++ b/clang/test/OpenMP/parallel_sections_if_messages.cpp @@ -9,6 +9,14 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp parallel sections if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + { + ; + } +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/target_data_if_messages.cpp b/clang/test/OpenMP/target_data_if_messages.cpp index c6f9b4b34eeeaf..29f898c6d9fa7e 100644 --- a/clang/test/OpenMP/target_data_if_messages.cpp +++ b/clang/test/OpenMP/target_data_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target data map(argc) if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} int main(int argc, char **argv) { diff --git a/clang/test/OpenMP/target_enter_data_if_messages.cpp b/clang/test/OpenMP/target_enter_data_if_messages.cpp index 5123d607dc6a18..21019e9ae7f8c4 100644 --- a/clang/test/OpenMP/target_enter_data_if_messages.cpp +++ b/clang/test/OpenMP/target_enter_data_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target enter data map(to:argc) if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} int main(int argc, char **argv) { diff --git a/clang/test/OpenMP/target_exit_data_if_messages.cpp b/clang/test/OpenMP/target_exit_data_if_messages.cpp index c45b32ff3fe757..7b2385c16cd213 100644 --- a/clang/test/OpenMP/target_exit_data_if_messages.cpp +++ b/clang/test/OpenMP/target_exit_data_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target exit data map(from: argc) if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} int main(int argc, char **argv) { diff --git a/clang/test/OpenMP/target_if_messages.cpp b/clang/test/OpenMP/target_if_messages.cpp index e6b667f2cffbf3..f381e9eb91ebd5 100644 --- a/clang/test/OpenMP/target_if_messages.cpp +++ b/clang/test/OpenMP/target_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/target_parallel_for_if_messages.cpp b/clang/test/OpenMP/target_parallel_for_if_messages.cpp index 445dc1775b0f29..a5a181b9d273af 100644 --- a/clang/test/OpenMP/target_parallel_for_if_messages.cpp +++ b/clang/test/OpenMP/target_parallel_for_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target parallel for if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/target_parallel_for_simd_if_messages.cpp b/clang/test/OpenMP/target_parallel_for_simd_if_messages.cpp index b0da8017019f0e..ef9a2089d1087f 100644 --- a/clang/test/OpenMP/target_parallel_for_simd_if_messages.cpp +++ b/clang/test/OpenMP/target_parallel_for_simd_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target parallel for simd if(parallel: cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/target_parallel_if_messages.cpp b/clang/test/OpenMP/target_parallel_if_messages.cpp index 460e0c8655f096..ac498a7108b0d1 100644 --- a/clang/test/OpenMP/target_parallel_if_messages.cpp +++ b/clang/test/OpenMP/target_parallel_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target parallel if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/target_simd_if_messages.cpp b/clang/test/OpenMP/target_simd_if_messages.cpp index 94d2ab308daa23..5f3e9e3910ac6e 100644 --- a/clang/test/OpenMP/target_simd_if_messages.cpp +++ b/clang/test/OpenMP/target_simd_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target simd if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/target_teams_distribute_if_messages.cpp b/clang/test/OpenMP/target_teams_distribute_if_messages.cpp index fd1ffb08cbe8cc..499cd3ac580505 100644 --- a/clang/test/OpenMP/target_teams_distribute_if_messages.cpp +++ b/clang/test/OpenMP/target_teams_distribute_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target teams distribute if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_if_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_if_messages.cpp index e1114028b68775..6df23076472ec5 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_if_messages.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target teams distribute parallel for if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_messages.cpp index 59c75893a17146..e88c1f1dbbfff1 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_messages.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_messages.cpp @@ -9,6 +9,14 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target teams distribute parallel for simd if (parallel \ + : cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/target_teams_distribute_simd_if_messages.cpp b/clang/test/OpenMP/target_teams_distribute_simd_if_messages.cpp index 7134a8394cbb85..53af6e759d21e5 100644 --- a/clang/test/OpenMP/target_teams_distribute_simd_if_messages.cpp +++ b/clang/test/OpenMP/target_teams_distribute_simd_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target teams distribute simd if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/target_teams_if_messages.cpp b/clang/test/OpenMP/target_teams_if_messages.cpp index 8d3d690d631fae..4bc82a349398d4 100644 --- a/clang/test/OpenMP/target_teams_if_messages.cpp +++ b/clang/test/OpenMP/target_teams_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target teams if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/target_update_if_messages.cpp b/clang/test/OpenMP/target_update_if_messages.cpp index 9ded332b04eb98..d967713e456fb6 100644 --- a/clang/test/OpenMP/target_update_if_messages.cpp +++ b/clang/test/OpenMP/target_update_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target update to(argc) if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/task_if_messages.cpp b/clang/test/OpenMP/task_if_messages.cpp index 305af22149d85e..2d47b32b9a1537 100644 --- a/clang/test/OpenMP/task_if_messages.cpp +++ b/clang/test/OpenMP/task_if_messages.cpp @@ -9,6 +9,13 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp task if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_if_messages.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_if_messages.cpp index 6f724b050178a6..b76599d41a46a0 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_if_messages.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_if_messages.cpp @@ -9,6 +9,14 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target +#pragma omp teams distribute parallel for if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_messages.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_messages.cpp index c01e6e87e39a54..39a0b326383a28 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_messages.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_if_messages.cpp @@ -9,6 +9,14 @@ bool foobool(int argc) { return argc; } +void xxx(int argc) { + int cond; // expected-note {{initialize the variable 'cond' to silence this warning}} +#pragma omp target +#pragma omp teams distribute parallel for simd if(cond) // expected-warning {{variable 'cond' is uninitialized when used here}} + for (int i = 0; i < 10; ++i) + ; +} + struct S1; // expected-note {{declared here}} template // expected-note {{declared here}} diff --git a/clang/test/PCH/non-trivial-c-union.m b/clang/test/PCH/non-trivial-c-union.m new file mode 100644 index 00000000000000..abd335497db266 --- /dev/null +++ b/clang/test/PCH/non-trivial-c-union.m @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -emit-pch -o %t.pch %s +// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -include-pch %t.pch -verify %s + +#ifndef HEADER +#define HEADER + +typedef union { + id f0; +} U0; + +#else + +// expected-note@-6 {{'U0' has subobjects that are non-trivial to destruct}} +// expected-note@-7 {{'U0' has subobjects that are non-trivial to copy}} +// expected-note@-8 {{'U0' has subobjects that are non-trivial to default-initialize}} +// expected-note@-8 {{f0 has type '__strong id' that is non-trivial to destruct}} +// expected-note@-9 {{f0 has type '__strong id' that is non-trivial to copy}} +// expected-note@-10 {{f0 has type '__strong id' that is non-trivial to default-initialize}} + +U0 foo0(void); // expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to copy}} + +U0 g0; // expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}} + +#endif diff --git a/clang/test/Parser/opencl-cxx-keywords.cl b/clang/test/Parser/opencl-cxx-keywords.cl index beae6f4b0895dc..0cafcdf28f868e 100644 --- a/clang/test/Parser/opencl-cxx-keywords.cl +++ b/clang/test/Parser/opencl-cxx-keywords.cl @@ -2,7 +2,7 @@ // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -verify -fsyntax-only -fexceptions -fcxx-exceptions // This test checks that various C++ and OpenCL C keywords are not available -// in OpenCL C++, according to OpenCL C++ 1.0 Specification Section 2.9. +// in OpenCL. // Test that exceptions are disabled despite passing -fcxx-exceptions. kernel void test_exceptions() { diff --git a/clang/test/Parser/opencl-cxx-virtual.cl b/clang/test/Parser/opencl-cxx-virtual.cl index da08bfde957ba9..53befbc32120b6 100644 --- a/clang/test/Parser/opencl-cxx-virtual.cl +++ b/clang/test/Parser/opencl-cxx-virtual.cl @@ -3,17 +3,17 @@ // Test that virtual functions and abstract classes are rejected. class virtual_functions { virtual void bad1() {} - //expected-error@-1 {{virtual functions are not supported in OpenCL C++}} + //expected-error@-1 {{virtual functions are not supported in C++ for OpenCL}} virtual void bad2() = 0; - //expected-error@-1 {{virtual functions are not supported in OpenCL C++}} + //expected-error@-1 {{virtual functions are not supported in C++ for OpenCL}} //expected-error@-2 {{'bad2' is not virtual and cannot be declared pure}} }; template class X { virtual T f(); - //expected-error@-1 {{virtual functions are not supported in OpenCL C++}} + //expected-error@-1 {{virtual functions are not supported in C++ for OpenCL}} }; // Test that virtual base classes are allowed. diff --git a/clang/test/Preprocessor/arm-target-features.c b/clang/test/Preprocessor/arm-target-features.c index 95231e2a8125a3..df5af4a933762c 100644 --- a/clang/test/Preprocessor/arm-target-features.c +++ b/clang/test/Preprocessor/arm-target-features.c @@ -762,12 +762,29 @@ // CHECK-V81M-MVE: #define __ARM_FEATURE_MVE 1 // CHECK-V81M-MVE: #define __ARM_FEATURE_SIMD32 1 -// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main+mve.fp -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V81M-MVE-FP %s -// CHECK-V81M-MVE-FP: #define __ARM_FEATURE_DSP 1 -// CHECK-V81M-MVE-FP: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1 -// CHECK-V81M-MVE-FP: #define __ARM_FEATURE_MVE 3 -// CHECK-V81M-MVE-FP: #define __ARM_FEATURE_SIMD32 1 -// CHECK-V81M-MVE-FP: #define __ARM_FPV5__ 1 +// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main+mve.fp -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V81M-MVEFP %s +// CHECK-V81M-MVEFP: #define __ARM_FEATURE_DSP 1 +// CHECK-V81M-MVEFP: #define __ARM_FEATURE_FP16_SCALAR_ARITHMETIC 1 +// CHECK-V81M-MVEFP: #define __ARM_FEATURE_MVE 3 +// CHECK-V81M-MVEFP: #define __ARM_FEATURE_SIMD32 1 +// CHECK-V81M-MVEFP: #define __ARM_FPV5__ 1 + +// nofp discards mve.fp +// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main+mve.fp+nofp -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V81M-MVEFP-NOFP %s +// CHECK-V81M-MVEFP-NOFP-NOT: #define __ARM_FEATURE_MVE + +// nomve discards mve.fp +// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main+mve.fp+nomve -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V81M-MVEFP-NOMVE %s +// CHECK-V81M-MVEFP-NOMVE-NOT: #define __ARM_FEATURE_MVE + +// mve+fp doesn't imply mve.fp +// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main+mve+fp -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V81M-MVE-FP %s +// CHECK-V81M-MVE-FP: #define __ARM_FEATURE_MVE 1 + +// nodsp discards both dsp and mve +// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main+mve+nodsp -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V81M-MVE-NODSP %s +// CHECK-V81M-MVE-NODSP-NOT: #define __ARM_FEATURE_MVE +// CHECK-V81M-MVE-NODSP-NOT: #define __ARM_FEATURE_DSP // RUN: %clang -target armv8.1a-none-none-eabi -x c -E -dM %s -o - | FileCheck -match-full-lines --check-prefix=CHECK-V81A %s // CHECK-V81A: #define __ARM_ARCH 8 diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c index 00a7c7b6bae95b..954f02a0143449 100644 --- a/clang/test/Preprocessor/init.c +++ b/clang/test/Preprocessor/init.c @@ -101,6 +101,7 @@ // COMMON:#define __ORDER_PDP_ENDIAN__ 3412 // COMMON:#define __STDC_HOSTED__ 1 // COMMON:#define __STDC__ 1 +// COMMON:#define __VERSION__ {{.*}} // COMMON:#define __clang__ 1 // COMMON:#define __clang_major__ {{[0-9]+}} // COMMON:#define __clang_minor__ {{[0-9]+}} @@ -8168,6 +8169,7 @@ // SPARC:#define __UINT_LEAST8_MAX__ 255 // SPARC:#define __UINT_LEAST8_TYPE__ unsigned char // SPARC:#define __USER_LABEL_PREFIX__ +// SPARC:#define __VERSION__ "{{.*}}Clang{{.*}} // SPARC:#define __WCHAR_MAX__ 2147483647 // SPARC:#define __WCHAR_TYPE__ int // SPARC:#define __WCHAR_WIDTH__ 32 @@ -9039,6 +9041,7 @@ // X86_64-CLOUDABI:#define __UINT_LEAST8_MAX__ 255 // X86_64-CLOUDABI:#define __UINT_LEAST8_TYPE__ unsigned char // X86_64-CLOUDABI:#define __USER_LABEL_PREFIX__ +// X86_64-CLOUDABI:#define __VERSION__ "{{.*}}Clang{{.*}} // X86_64-CLOUDABI:#define __WCHAR_MAX__ 2147483647 // X86_64-CLOUDABI:#define __WCHAR_TYPE__ int // X86_64-CLOUDABI:#define __WCHAR_WIDTH__ 32 @@ -10040,6 +10043,7 @@ // WEBASSEMBLY-NEXT:#define __UINT_LEAST8_MAX__ 255 // WEBASSEMBLY-NEXT:#define __UINT_LEAST8_TYPE__ unsigned char // WEBASSEMBLY-NEXT:#define __USER_LABEL_PREFIX__ +// WEBASSEMBLY-NEXT:#define __VERSION__ "{{.*}}" // WEBASSEMBLY-NEXT:#define __WCHAR_MAX__ 2147483647 // WEBASSEMBLY-NEXT:#define __WCHAR_TYPE__ int // WEBASSEMBLY-NOT:#define __WCHAR_UNSIGNED__ diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 2c63e0fa29dfbe..36e49c36f03302 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -47,3 +47,27 @@ // RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64ic -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-C-EXT %s // CHECK-C-EXT: __riscv_compressed 1 + +// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32ifd -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-SOFT %s +// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64ifd -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-SOFT %s +// CHECK-SOFT: __riscv_float_abi_soft 1 +// CHECK-SOFT-NOT: __riscv_float_abi_single +// CHECK-SOFT-NOT: __riscv_float_abi_double + +// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32ifd -mabi=ilp32f -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-SINGLE %s +// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64ifd -mabi=lp64f -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-SINGLE %s +// CHECK-SINGLE: __riscv_float_abi_single 1 +// CHECK-SINGLE-NOT: __riscv_float_abi_soft +// CHECK-SINGLE-NOT: __riscv_float_abi_double + +// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32ifd -mabi=ilp32d -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-DOUBLE %s +// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64ifd -mabi=lp64d -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-DOUBLE %s +// CHECK-DOUBLE: __riscv_float_abi_double 1 +// CHECK-DOUBLE-NOT: __riscv_float_abi_soft +// CHECK-DOUBLE-NOT: __riscv_float_abi_single diff --git a/clang/test/Preprocessor/x86_seg_fs_gs.c b/clang/test/Preprocessor/x86_seg_fs_gs.c new file mode 100644 index 00000000000000..b7a586c820245a --- /dev/null +++ b/clang/test/Preprocessor/x86_seg_fs_gs.c @@ -0,0 +1,7 @@ +// RUN: %clang -target i386-unknown-unknown -x c -E -dM -o - %s | FileCheck -match-full-lines %s +// RUN: %clang -target x86_64-unknown-unknown -x c -E -dM -o - %s | FileCheck -match-full-lines %s + +// CHECK: #define __SEG_FS 1 +// CHECK: #define __SEG_GS 1 +// CHECK: #define __seg_fs __attribute__((address_space(257))) +// CHECK: #define __seg_gs __attribute__((address_space(256))) diff --git a/clang/test/Sema/builtin-preserve-access-index.c b/clang/test/Sema/builtin-preserve-access-index.c new file mode 100644 index 00000000000000..c10ceb5145b8c3 --- /dev/null +++ b/clang/test/Sema/builtin-preserve-access-index.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -x c -triple x86_64-pc-linux-gnu -dwarf-version=4 -fsyntax-only -verify %s + +const void *invalid1(const int *arg) { + return __builtin_preserve_access_index(&arg[1], 1); // expected-error {{too many arguments to function call, expected 1, have 2}} +} + +void *invalid2(const int *arg) { + return __builtin_preserve_access_index(&arg[1]); // expected-warning {{returning 'const void *' from a function with result type 'void *' discards qualifiers}} +} + +const void *invalid3(const int *arg) { + return __builtin_preserve_access_index(1); // expected-warning {{incompatible integer to pointer conversion passing 'int' to parameter of type 'const void *'}} +} diff --git a/clang/test/Sema/callingconv-iamcu.c b/clang/test/Sema/callingconv-iamcu.c index 2c99b029b6a287..248e98b0d01df8 100644 --- a/clang/test/Sema/callingconv-iamcu.c +++ b/clang/test/Sema/callingconv-iamcu.c @@ -1,35 +1,35 @@ // RUN: %clang_cc1 %s -fsyntax-only -triple i686-intel-elfiamcu -verify -void __attribute__((fastcall)) foo(float *a) { // expected-warning {{'fastcall' calling convention ignored for this target}} +void __attribute__((fastcall)) foo(float *a) { // expected-warning {{'fastcall' calling convention is not supported for this target}} } -void __attribute__((stdcall)) bar(float *a) { // expected-warning {{'stdcall' calling convention ignored for this target}} +void __attribute__((stdcall)) bar(float *a) { // expected-warning {{'stdcall' calling convention is not supported for this target}} } void __attribute__((fastcall(1))) baz(float *a) { // expected-error {{'fastcall' attribute takes no arguments}} } -void __attribute__((fastcall)) test2(int a, ...) { // expected-warning {{'fastcall' calling convention ignored for this target}} +void __attribute__((fastcall)) test2(int a, ...) { // expected-warning {{'fastcall' calling convention is not supported for this target}} } -void __attribute__((stdcall)) test3(int a, ...) { // expected-warning {{'stdcall' calling convention ignored for this target}} +void __attribute__((stdcall)) test3(int a, ...) { // expected-warning {{'stdcall' calling convention is not supported for this target}} } -void __attribute__((thiscall)) test4(int a, ...) { // expected-warning {{'thiscall' calling convention ignored for this target}} +void __attribute__((thiscall)) test4(int a, ...) { // expected-warning {{'thiscall' calling convention is not supported for this target}} } void __attribute__((cdecl)) ctest0() {} void __attribute__((cdecl(1))) ctest1(float x) {} // expected-error {{'cdecl' attribute takes no arguments}} -void (__attribute__((fastcall)) *pfoo)(float*) = foo; // expected-warning {{'fastcall' calling convention ignored for this target}} +void (__attribute__((fastcall)) *pfoo)(float*) = foo; // expected-warning {{'fastcall' calling convention is not supported for this target}} -void (__attribute__((stdcall)) *pbar)(float*) = bar; // expected-warning {{'stdcall' calling convention ignored for this target}} +void (__attribute__((stdcall)) *pbar)(float*) = bar; // expected-warning {{'stdcall' calling convention is not supported for this target}} void (*pctest0)() = ctest0; void ctest2() {} void (__attribute__((cdecl)) *pctest2)() = ctest2; -typedef void (__attribute__((fastcall)) *Handler) (float *); // expected-warning {{'fastcall' calling convention ignored for this target}} +typedef void (__attribute__((fastcall)) *Handler) (float *); // expected-warning {{'fastcall' calling convention is not supported for this target}} Handler H = foo; int __attribute__((pcs("aapcs", "aapcs"))) pcs1(void); // expected-error {{'pcs' attribute takes one argument}} @@ -38,16 +38,16 @@ int __attribute__((pcs(pcs1))) pcs3(void); // expected-error {{'pcs' attribute r // expected-error {{invalid PCS type}} int __attribute__((pcs(0))) pcs4(void); // expected-error {{'pcs' attribute requires a string}} /* These are ignored because the target is i386 and not ARM */ -int __attribute__((pcs("aapcs"))) pcs5(void); // expected-warning {{'pcs' calling convention ignored for this target}} -int __attribute__((pcs("aapcs-vfp"))) pcs6(void); // expected-warning {{'pcs' calling convention ignored for this target}} +int __attribute__((pcs("aapcs"))) pcs5(void); // expected-warning {{'pcs' calling convention is not supported for this target}} +int __attribute__((pcs("aapcs-vfp"))) pcs6(void); // expected-warning {{'pcs' calling convention is not supported for this target}} int __attribute__((pcs("foo"))) pcs7(void); // expected-error {{invalid PCS type}} void ctest3(); void __attribute__((cdecl)) ctest3() {} -typedef __attribute__((stdcall)) void (*PROC)(); // expected-warning {{'stdcall' calling convention ignored for this target}} +typedef __attribute__((stdcall)) void (*PROC)(); // expected-warning {{'stdcall' calling convention is not supported for this target}} PROC __attribute__((cdecl)) ctest4(const char *x) {} -void __attribute__((intel_ocl_bicc)) inteloclbifunc(float *a) {} // expected-warning {{'intel_ocl_bicc' calling convention ignored for this target}} +void __attribute__((intel_ocl_bicc)) inteloclbifunc(float *a) {} // expected-warning {{'intel_ocl_bicc' calling convention is not supported for this target}} -struct type_test {} __attribute__((stdcall)); // expected-warning {{'stdcall' calling convention ignored for this target}} expected-warning {{'stdcall' attribute only applies to functions and methods}} +struct type_test {} __attribute__((stdcall)); // expected-warning {{'stdcall' calling convention is not supported for this target}} expected-warning {{'stdcall' attribute only applies to functions and methods}} diff --git a/clang/test/Sema/callingconv.c b/clang/test/Sema/callingconv.c index e6d6ad2c12048a..6273d04f21217d 100644 --- a/clang/test/Sema/callingconv.c +++ b/clang/test/Sema/callingconv.c @@ -16,9 +16,9 @@ void __attribute__((fastcall)) test0() { void __attribute__((fastcall)) test1(void) { } -void __attribute__((fastcall)) test2(int a, ...) { // expected-warning {{fastcall calling convention ignored on variadic function}} +void __attribute__((fastcall)) test2(int a, ...) { // expected-warning {{fastcall calling convention is not supported on variadic function}} } -void __attribute__((stdcall)) test3(int a, ...) { // expected-warning {{stdcall calling convention ignored on variadic function}} +void __attribute__((stdcall)) test3(int a, ...) { // expected-warning {{stdcall calling convention is not supported on variadic function}} } void __attribute__((thiscall)) test4(int a, ...) { // expected-error {{variadic function cannot use thiscall calling convention}} } @@ -47,11 +47,11 @@ int __attribute__((pcs(pcs1))) pcs3(void); // expected-error {{'pcs' attribute r // expected-error {{invalid PCS type}} int __attribute__((pcs(0))) pcs4(void); // expected-error {{'pcs' attribute requires a string}} /* These are ignored because the target is i386 and not ARM */ -int __attribute__((pcs("aapcs"))) pcs5(void); // expected-warning {{'pcs' calling convention ignored for this target}} -int __attribute__((pcs("aapcs-vfp"))) pcs6(void); // expected-warning {{'pcs' calling convention ignored for this target}} +int __attribute__((pcs("aapcs"))) pcs5(void); // expected-warning {{'pcs' calling convention is not supported for this target}} +int __attribute__((pcs("aapcs-vfp"))) pcs6(void); // expected-warning {{'pcs' calling convention is not supported for this target}} int __attribute__((pcs("foo"))) pcs7(void); // expected-error {{invalid PCS type}} -int __attribute__((aarch64_vector_pcs)) aavpcs(void); // expected-warning {{'aarch64_vector_pcs' calling convention ignored for this target}} +int __attribute__((aarch64_vector_pcs)) aavpcs(void); // expected-warning {{'aarch64_vector_pcs' calling convention is not supported for this target}} // PR6361 void ctest3(); @@ -69,4 +69,4 @@ void __attribute__((stdcall)) typedef_fun(int x) { } // expected-error {{functio struct type_test {} __attribute__((stdcall)); // expected-warning {{'stdcall' attribute only applies to functions and methods}} -void __vectorcall __builtin_unreachable(); // expected-warning {{vectorcall calling convention ignored on builtin function}} +void __vectorcall __builtin_unreachable(); // expected-warning {{vectorcall calling convention is not supported on builtin function}} diff --git a/clang/test/Sema/mrtd.c b/clang/test/Sema/mrtd.c index 7bdeb27293b780..0ce08880606435 100644 --- a/clang/test/Sema/mrtd.c +++ b/clang/test/Sema/mrtd.c @@ -12,7 +12,7 @@ void __attribute__((stdcall)) nonvariadic1(int a, int b, int c); void nonvariadic2(int a, int b, int c); void __attribute__((stdcall)) nonvariadic2(int a, int b, int c) { } -// expected-warning@+2 {{stdcall calling convention ignored on variadic function}} +// expected-warning@+2 {{stdcall calling convention is not supported on variadic function}} void variadic(int a, ...); void __attribute__((stdcall)) variadic(int a, ...); @@ -33,6 +33,6 @@ __attribute__((cdecl)) extern void (*b)(int, ...); extern void (*c)(int, int); __attribute__((stdcall)) extern void (*c)(int, int); -// expected-warning@+2 {{stdcall calling convention ignored on variadic function}} +// expected-warning@+2 {{stdcall calling convention is not supported on variadic function}} extern void (*d)(int, ...); __attribute__((stdcall)) extern void (*d)(int, ...); diff --git a/clang/test/Sema/pr25786.c b/clang/test/Sema/pr25786.c index bfc2b35ede2392..f79d8144716b1f 100644 --- a/clang/test/Sema/pr25786.c +++ b/clang/test/Sema/pr25786.c @@ -2,8 +2,8 @@ // RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fsyntax-only -verify %s #if TEST -void (__attribute__((regparm(3), stdcall)) *pf) (); //expected-warning {{'stdcall' calling convention ignored for this target}} -void (__attribute__((regparm(2), stdcall)) foo)(int a) { //expected-warning {{'stdcall' calling convention ignored for this target}} +void (__attribute__((regparm(3), stdcall)) *pf) (); //expected-warning {{'stdcall' calling convention is not supported for this target}} +void (__attribute__((regparm(2), stdcall)) foo)(int a) { //expected-warning {{'stdcall' calling convention is not supported for this target}} } #else //expected-no-diagnostics diff --git a/clang/test/Sema/stdcall-fastcall-x64.c b/clang/test/Sema/stdcall-fastcall-x64.c index e2e39e434f8100..335da4169352a3 100644 --- a/clang/test/Sema/stdcall-fastcall-x64.c +++ b/clang/test/Sema/stdcall-fastcall-x64.c @@ -5,16 +5,16 @@ int __attribute__((stdcall)) var1; // expected-warning{{'stdcall' only applies t int __attribute__((fastcall)) var2; // expected-warning{{'fastcall' only applies to function types; type here is 'int'}} // Different CC qualifiers are not compatible -void __attribute__((stdcall, fastcall)) foo3(void); // expected-warning{{'stdcall' calling convention ignored for this target}} expected-warning {{'fastcall' calling convention ignored for this target}} -void __attribute__((stdcall)) foo4(); // expected-warning{{'stdcall' calling convention ignored for this target}} -void __attribute__((fastcall)) foo4(void); // expected-warning {{'fastcall' calling convention ignored for this target}} +void __attribute__((stdcall, fastcall)) foo3(void); // expected-warning{{'stdcall' calling convention is not supported for this target}} expected-warning {{'fastcall' calling convention is not supported for this target}} +void __attribute__((stdcall)) foo4(); // expected-warning{{'stdcall' calling convention is not supported for this target}} +void __attribute__((fastcall)) foo4(void); // expected-warning {{'fastcall' calling convention is not supported for this target}} // rdar://8876096 -void rdar8876096foo1(int i, int j) __attribute__((fastcall, cdecl)); // expected-warning{{'fastcall' calling convention ignored for this target}} -void rdar8876096foo2(int i, int j) __attribute__((fastcall, stdcall)); // expected-warning{{'stdcall' calling convention ignored for this target}} expected-warning {{'fastcall' calling convention ignored for this target}} -void rdar8876096foo3(int i, int j) __attribute__((fastcall, regparm(2))); // expected-warning {{'fastcall' calling convention ignored for this target}} -void rdar8876096foo4(int i, int j) __attribute__((stdcall, cdecl)); // expected-warning{{'stdcall' calling convention ignored for this target}} -void rdar8876096foo5(int i, int j) __attribute__((stdcall, fastcall)); // expected-warning{{'stdcall' calling convention ignored for this target}} expected-warning {{'fastcall' calling convention ignored for this target}} -void rdar8876096foo6(int i, int j) __attribute__((cdecl, fastcall)); // expected-warning {{'fastcall' calling convention ignored for this target}} -void rdar8876096foo7(int i, int j) __attribute__((cdecl, stdcall)); // expected-warning{{'stdcall' calling convention ignored for this target}} -void rdar8876096foo8(int i, int j) __attribute__((regparm(2), fastcall)); // expected-warning {{'fastcall' calling convention ignored for this target}} +void rdar8876096foo1(int i, int j) __attribute__((fastcall, cdecl)); // expected-warning{{'fastcall' calling convention is not supported for this target}} +void rdar8876096foo2(int i, int j) __attribute__((fastcall, stdcall)); // expected-warning{{'stdcall' calling convention is not supported for this target}} expected-warning {{'fastcall' calling convention is not supported for this target}} +void rdar8876096foo3(int i, int j) __attribute__((fastcall, regparm(2))); // expected-warning {{'fastcall' calling convention is not supported for this target}} +void rdar8876096foo4(int i, int j) __attribute__((stdcall, cdecl)); // expected-warning{{'stdcall' calling convention is not supported for this target}} +void rdar8876096foo5(int i, int j) __attribute__((stdcall, fastcall)); // expected-warning{{'stdcall' calling convention is not supported for this target}} expected-warning {{'fastcall' calling convention is not supported for this target}} +void rdar8876096foo6(int i, int j) __attribute__((cdecl, fastcall)); // expected-warning {{'fastcall' calling convention is not supported for this target}} +void rdar8876096foo7(int i, int j) __attribute__((cdecl, stdcall)); // expected-warning{{'stdcall' calling convention is not supported for this target}} +void rdar8876096foo8(int i, int j) __attribute__((regparm(2), fastcall)); // expected-warning {{'fastcall' calling convention is not supported for this target}} diff --git a/clang/test/Sema/zero-initializer.c b/clang/test/Sema/zero-initializer.c index 0ab410d4c6d551..e54021a582c524 100644 --- a/clang/test/Sema/zero-initializer.c +++ b/clang/test/Sema/zero-initializer.c @@ -7,6 +7,8 @@ struct A { int a; }; struct B { struct A a; }; struct C { struct B b; }; struct D { struct C c; int n; }; +struct E { short e; }; +struct F { struct E e; int n; }; int main(void) { @@ -23,6 +25,9 @@ int main(void) struct C p = { 0 }; // no-warning struct C q = { 9 }; // warning suppressed for struct with single element struct D r = { 9 }; // expected-warning {{suggest braces around initialization of subobject}} expected-warning {{missing field 'n' initializer}} + struct F s = { 0 }; // no-warning + struct F t = { 9 }; // expected-warning {{suggest braces around initialization of subobject}} expected-warning {{missing field 'n' initializer}} + f = (struct foo ) { 0 }; // no-warning g = (struct foo ) { 9 }; // expected-warning {{missing field 'y' initializer}} h = (struct foo ) { 9, 9 }; // no-warning @@ -36,6 +41,8 @@ int main(void) p = (struct C) { 0 }; // no-warning q = (struct C) { 9 }; // warning suppressed for struct with single element r = (struct D) { 9 }; // expected-warning {{suggest braces around initialization of subobject}} expected-warning {{missing field 'n' initializer}} + s = (struct F) { 0 }; // no-warning + t = (struct F) { 9 }; // expected-warning {{suggest braces around initialization of subobject}} expected-warning {{missing field 'n' initializer}} return 0; } diff --git a/clang/test/SemaCUDA/cuda-inherits-calling-conv.cu b/clang/test/SemaCUDA/cuda-inherits-calling-conv.cu index 881f2945b1b347..a6928e71f3ae09 100644 --- a/clang/test/SemaCUDA/cuda-inherits-calling-conv.cu +++ b/clang/test/SemaCUDA/cuda-inherits-calling-conv.cu @@ -24,7 +24,7 @@ struct Foo {}; // expected-no-diagnostics #else // expected-error@+4 {{redefinition of 'Foo}} -// expected-warning@+3 {{'__fastcall' calling convention ignored}} +// expected-warning@+3 {{'__fastcall' calling convention is not supported}} #endif template struct Foo {}; diff --git a/clang/test/SemaCXX/attr-no-sanitize.cpp b/clang/test/SemaCXX/attr-no-sanitize.cpp index 02bc9a9e7f8f4b..feff7ef6163dc2 100644 --- a/clang/test/SemaCXX/attr-no-sanitize.cpp +++ b/clang/test/SemaCXX/attr-no-sanitize.cpp @@ -30,3 +30,8 @@ int f5() __attribute__((no_sanitize("address", "thread", "hwaddress"))); // DUMP: NoSanitizeAttr {{.*}} unknown // PRINT: int f6() __attribute__((no_sanitize("unknown"))) int f6() __attribute__((no_sanitize("unknown"))); // expected-warning{{unknown sanitizer 'unknown' ignored}} + +// DUMP-LABEL: FunctionDecl {{.*}} f7 +// DUMP: NoSanitizeAttr {{.*}} memtag +// PRINT: int f7() {{\[\[}}clang::no_sanitize("memtag")]] +[[clang::no_sanitize("memtag")]] int f7(); diff --git a/clang/test/SemaCXX/borland-extensions.cpp b/clang/test/SemaCXX/borland-extensions.cpp index 31ebf037129249..a869f4ee60e90d 100644 --- a/clang/test/SemaCXX/borland-extensions.cpp +++ b/clang/test/SemaCXX/borland-extensions.cpp @@ -7,21 +7,21 @@ int dummy_function() { return 0; } // 2. test __pascal -// expected-warning@+1 {{'_pascal' calling convention ignored for this target}} +// expected-warning@+1 {{'_pascal' calling convention is not supported for this target}} int _pascal f2(); -// expected-warning@+1 {{'__pascal' calling convention ignored for this target}} +// expected-warning@+1 {{'__pascal' calling convention is not supported for this target}} float __pascal gi2(int, int); -// expected-warning@+1 {{'__pascal' calling convention ignored for this target}} +// expected-warning@+1 {{'__pascal' calling convention is not supported for this target}} template T g2(T (__pascal * const )(int, int)) { return 0; } struct M { - // expected-warning@+1 {{'__pascal' calling convention ignored for this target}} + // expected-warning@+1 {{'__pascal' calling convention is not supported for this target}} int __pascal addP(); - // expected-warning@+1 {{'__pascal' calling convention ignored for this target}} + // expected-warning@+1 {{'__pascal' calling convention is not supported for this target}} float __pascal subtractP(); }; -// expected-warning@+1 {{'__pascal' calling convention ignored for this target}} +// expected-warning@+1 {{'__pascal' calling convention is not supported for this target}} template int h2(T (__pascal M::* const )()) { return 0; } void m2() { int i; float f; @@ -34,9 +34,9 @@ void m2() { // 3. test other calling conventions int _cdecl fa3(); -// expected-warning@+1 {{'_fastcall' calling convention ignored for this target}} +// expected-warning@+1 {{'_fastcall' calling convention is not supported for this target}} int _fastcall fc3(); -// expected-warning@+1 {{'_stdcall' calling convention ignored for this target}} +// expected-warning@+1 {{'_stdcall' calling convention is not supported for this target}} int _stdcall fd3(); // 4. test __uuidof() diff --git a/clang/test/SemaCXX/cxx11-gnu-attrs.cpp b/clang/test/SemaCXX/cxx11-gnu-attrs.cpp index 1e8ad1e495bbfc..a91cb278b4d241 100644 --- a/clang/test/SemaCXX/cxx11-gnu-attrs.cpp +++ b/clang/test/SemaCXX/cxx11-gnu-attrs.cpp @@ -9,18 +9,18 @@ int [[gnu::unused]] attr_on_type; int *[[gnu::unused]] attr_on_ptr; // expected-warning@-1 {{attribute 'unused' ignored, because it cannot be applied to a type}} [[gnu::fastcall]] void pr17424_1(); -// expected-warning@-1 {{'fastcall' calling convention ignored for this target}} +// expected-warning@-1 {{'fastcall' calling convention is not supported for this target}} [[gnu::fastcall]] [[gnu::stdcall]] void pr17424_2(); -// expected-warning@-1 {{'fastcall' calling convention ignored for this target}} -// expected-warning@-2 {{'stdcall' calling convention ignored for this target}} +// expected-warning@-1 {{'fastcall' calling convention is not supported for this target}} +// expected-warning@-2 {{'stdcall' calling convention is not supported for this target}} [[gnu::fastcall]] __stdcall void pr17424_3(); -// expected-warning@-1 {{'fastcall' calling convention ignored for this target}} -// expected-warning@-2 {{'__stdcall' calling convention ignored for this target}} +// expected-warning@-1 {{'fastcall' calling convention is not supported for this target}} +// expected-warning@-2 {{'__stdcall' calling convention is not supported for this target}} [[gnu::fastcall]] void pr17424_4() [[gnu::stdcall]]; -// expected-warning@-1 {{'fastcall' calling convention ignored for this target}} -// expected-warning@-2 {{'stdcall' calling convention ignored for this target}} +// expected-warning@-1 {{'fastcall' calling convention is not supported for this target}} +// expected-warning@-2 {{'stdcall' calling convention is not supported for this target}} void pr17424_5 [[gnu::fastcall]](); -// expected-warning@-1 {{'fastcall' calling convention ignored for this target}} +// expected-warning@-1 {{'fastcall' calling convention is not supported for this target}} // Valid cases. diff --git a/clang/test/SemaCXX/decl-microsoft-call-conv.cpp b/clang/test/SemaCXX/decl-microsoft-call-conv.cpp index acd9b0720b6202..a2a04ac9c8b993 100644 --- a/clang/test/SemaCXX/decl-microsoft-call-conv.cpp +++ b/clang/test/SemaCXX/decl-microsoft-call-conv.cpp @@ -77,7 +77,7 @@ struct S { // Structors can't be other than default in MS ABI environment #ifdef MSABI - __vectorcall S(); // expected-warning {{vectorcall calling convention ignored on constructor/destructor}} + __vectorcall S(); // expected-warning {{vectorcall calling convention is not supported on constructor/destructor}} #endif }; diff --git a/clang/test/SemaCXX/virtual-override-x64.cpp b/clang/test/SemaCXX/virtual-override-x64.cpp index 5b9b2148f00a5a..f3eaf11569c8f7 100644 --- a/clang/test/SemaCXX/virtual-override-x64.cpp +++ b/clang/test/SemaCXX/virtual-override-x64.cpp @@ -6,7 +6,7 @@ namespace PR14339 { class A { public: - virtual void __attribute__((thiscall)) f(); // expected-warning {{'thiscall' calling convention ignored for this target}} + virtual void __attribute__((thiscall)) f(); // expected-warning {{'thiscall' calling convention is not supported for this target}} }; class B : public A { @@ -16,7 +16,7 @@ namespace PR14339 { class C : public A { public: - void __attribute__((thiscall)) f(); // expected-warning {{'thiscall' calling convention ignored for this target}} + void __attribute__((thiscall)) f(); // expected-warning {{'thiscall' calling convention is not supported for this target}} }; class D : public A { @@ -26,7 +26,7 @@ namespace PR14339 { class E { public: - virtual void __attribute__((stdcall)) g(); // expected-warning {{'stdcall' calling convention ignored for this target}} + virtual void __attribute__((stdcall)) g(); // expected-warning {{'stdcall' calling convention is not supported for this target}} }; class F : public E { diff --git a/clang/test/SemaObjC/arc-decls.m b/clang/test/SemaObjC/arc-decls.m index 0abd45dac33e2b..28c3de996996d1 100644 --- a/clang/test/SemaObjC/arc-decls.m +++ b/clang/test/SemaObjC/arc-decls.m @@ -8,11 +8,7 @@ }; union u { - id u; // expected-error {{ARC forbids Objective-C objects in union}} -}; - -union u_nontrivial_c { - struct A a; // expected-error {{non-trivial C types are disallowed in union}} + id u; }; // Volatile fields are fine. diff --git a/clang/test/SemaObjC/non-trivial-c-union.m b/clang/test/SemaObjC/non-trivial-c-union.m new file mode 100644 index 00000000000000..7bd82775451c80 --- /dev/null +++ b/clang/test/SemaObjC/non-trivial-c-union.m @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -fsyntax-only -fblocks -fobjc-arc -fobjc-runtime-has-weak -verify %s + +typedef union { // expected-note 12 {{'U0' has subobjects that are non-trivial to default-initialize}} expected-note 36 {{'U0' has subobjects that are non-trivial to destruct}} expected-note 28 {{'U0' has subobjects that are non-trivial to copy}} + id f0; // expected-note 12 {{f0 has type '__strong id' that is non-trivial to default-initialize}} expected-note 36 {{f0 has type '__strong id' that is non-trivial to destruct}} expected-note 28 {{f0 has type '__strong id' that is non-trivial to copy}} + __weak id f1; // expected-note 12 {{f1 has type '__weak id' that is non-trivial to default-initialize}} expected-note 36 {{f1 has type '__weak id' that is non-trivial to destruct}} expected-note 28 {{f1 has type '__weak id' that is non-trivial to copy}} +} U0; + +typedef struct { + U0 f0; + id f1; +} S0; + +id g0; +U0 ug0; // expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}} +U0 ug1 = { .f0 = 0 }; +S0 sg0; // expected-error {{cannot default-initialize an object of type 'S0' since it contains a union that is non-trivial to default-initialize}} +S0 sg1 = { .f0 = {0}, .f1 = 0 }; +S0 sg2 = { .f1 = 0 }; // expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}} + +U0 foo0(U0); // expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to copy}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to copy}} +S0 foo1(S0); // expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to copy}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to copy}} + +@interface C +-(U0)m0:(U0)arg; // expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to copy}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to copy}} +-(S0)m1:(S0)arg; // expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to copy}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to copy}} +@end + +void testBlockFunction(void) { + (void)^(U0 a){ return ug0; }; // expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to copy}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to copy}} + (void)^(S0 a){ return sg0; }; // expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to copy}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to copy}} +} +void testAutoVar(void) { + U0 u0; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}} + U0 u1 = ug0; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot copy-initialize an object of type 'U0' since it is a union that is non-trivial to copy}} + U0 u2 = { g0 }; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}} + U0 u3 = { .f1 = g0 }; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}} + S0 s0; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'S0' since it contains a union that is non-trivial to default-initialize}} + S0 s1 = sg0; // expected-error {{declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot copy-initialize an object of type 'S0' since it contains a union that is non-trivial to copy}} + S0 s2 = { ug0 }; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot copy-initialize an object of type 'U0' since it is a union that is non-trivial to copy}} + S0 s3 = { .f0 = ug0 }; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot copy-initialize an object of type 'U0' since it is a union that is non-trivial to copy}} + S0 s4 = { .f1 = g0 }; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}} +} + +void testAssignment(void) { + ug0 = ug1; // expected-error {{cannot assign to a variable of type 'U0' since it is a union that is non-trivial to copy}} + sg0 = sg1; // expected-error {{cannot assign to a variable of type 'S0' since it contains a union that is non-trivial to copy}} +} + +U0 ug2 = (U0){ .f1 = 0 }; // expected-error {{cannot copy-initialize an object of type 'U0' since it is a union that is non-trivial to copy}} +S0 sg3 = (S0){ .f0 = {0}, .f1 = 0 }; // expected-error {{cannot copy-initialize an object of type 'S0' since it contains a union that is non-trivial to copy}} +S0 *sg4 = &(S0){ .f1 = 0 }; // expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}} + +void testCompoundLiteral(void) { + const U0 *t0 = &(U0){ .f0 = g0 }; // expected-error {{cannot construct an automatic compound literal of type 'U0' since it is a union that is non-trivial to destruct}} + const U0 *t1 = &(U0){ .f1 = g0 }; // expected-error {{cannot construct an automatic compound literal of type 'U0' since it is a union that is non-trivial to destruct}} + const S0 *t2 = &(S0){ .f0 = ug0 }; // expected-error {{cannot construct an automatic compound literal of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot copy-initialize an object of type 'U0' since it is a union that is non-trivial to copy}} + const S0 *t3 = &(S0){ .f1 = g0 }; // expected-error {{cannot construct an automatic compound literal of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}} +} + +typedef void (^BlockTy)(void); +void escapingFunc(BlockTy); +void noescapingFunc(__attribute__((noescape)) BlockTy); + +void testBlockCapture(void) { + U0 t0; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}} + S0 t1; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'S0' since it contains a union that is non-trivial to default-initialize}} + __block U0 t2; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}} + __block S0 t3; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'S0' since it contains a union that is non-trivial to default-initialize}} + + escapingFunc(^{ g0 = t0.f0; }); // expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to copy}} + escapingFunc(^{ g0 = t1.f0.f0; }); // expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to copy}} + escapingFunc(^{ g0 = t2.f0; }); // expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to copy}} + escapingFunc(^{ g0 = t3.f0.f0; }); // expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to copy}} + noescapingFunc(^{ g0 = t0.f0; }); // expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to copy}} + noescapingFunc(^{ g0 = t1.f0.f0; }); // expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to copy}} + noescapingFunc(^{ g0 = t2.f0; }); + noescapingFunc(^{ g0 = t3.f0.f0; }); +} + +void testVolatileLValueToRValue(volatile U0 *a) { + (void)*a; // expected-error {{cannot use volatile type 'volatile U0' where it causes an lvalue-to-rvalue conversion since it is a union that is non-trivial to destruct}} // expected-error {{cannot use volatile type 'volatile U0' where it causes an lvalue-to-rvalue conversion since it is a union that is non-trivial to copy}} +} diff --git a/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx10-param.cl b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx10-param.cl new file mode 100644 index 00000000000000..75d9cd3831c55f --- /dev/null +++ b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx10-param.cl @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple amdgcn-- -target-cpu gfx1010 -verify -S -o - %s + +typedef unsigned int uint; + + +void test_permlane16(global uint* out, uint a, uint b, uint c, uint d, uint e) { + *out = __builtin_amdgcn_permlane16(a, b, c, d, e, 1); // expected-error{{argument to '__builtin_amdgcn_permlane16' must be a constant integer}} + *out = __builtin_amdgcn_permlane16(a, b, c, d, 1, e); // expected-error{{argument to '__builtin_amdgcn_permlane16' must be a constant integer}} +} + +void test_permlanex16(global uint* out, uint a, uint b, uint c, uint d, uint e) { + *out = __builtin_amdgcn_permlanex16(a, b, c, d, e, 1); // expected-error{{argument to '__builtin_amdgcn_permlanex16' must be a constant integer}} + *out = __builtin_amdgcn_permlanex16(a, b, c, d, 1, e); // expected-error{{argument to '__builtin_amdgcn_permlanex16' must be a constant integer}} +} + +void test_mov_dpp8(global uint* out, uint a, uint b) { + *out = __builtin_amdgcn_mov_dpp8(a, b); // expected-error{{argument to '__builtin_amdgcn_mov_dpp8' must be a constant integer}} +} diff --git a/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx10.cl b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx10.cl new file mode 100644 index 00000000000000..02c8dc8c1339ee --- /dev/null +++ b/clang/test/SemaOpenCL/builtins-amdgcn-error-gfx10.cl @@ -0,0 +1,15 @@ +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -triple amdgcn-- -target-cpu tahiti -verify -S -o - %s +// RUN: %clang_cc1 -triple amdgcn-- -target-cpu hawaii -verify -S -o - %s +// RUN: %clang_cc1 -triple amdgcn-- -target-cpu fiji -verify -S -o - %s +// RUN: %clang_cc1 -triple amdgcn-- -target-cpu gfx900 -verify -S -o - %s +// RUN: %clang_cc1 -triple amdgcn-- -target-cpu gfx908 -verify -S -o - %s + +typedef unsigned int uint; + + +void test(global uint* out, uint a, uint b, uint c, uint d) { + *out = __builtin_amdgcn_permlane16(a, b, c, d, 1, 1); // expected-error {{'__builtin_amdgcn_permlane16' needs target feature gfx10-insts}} + *out = __builtin_amdgcn_permlanex16(a, b, c, d, 1, 1); // expected-error {{'__builtin_amdgcn_permlanex16' needs target feature gfx10-insts}} + *out = __builtin_amdgcn_mov_dpp8(a, 1); // expected-error {{'__builtin_amdgcn_mov_dpp8' needs target feature gfx10-insts}} +} diff --git a/clang/test/SemaOpenCLCXX/address-space-deduction.cl b/clang/test/SemaOpenCLCXX/address-space-deduction.cl index 6b2a07cad748b7..4283ec41e63565 100644 --- a/clang/test/SemaOpenCLCXX/address-space-deduction.cl +++ b/clang/test/SemaOpenCLCXX/address-space-deduction.cl @@ -24,3 +24,57 @@ struct c2 { alias_c1_ptr ptr = &y; }; + +// Addr spaces for pointee of dependent types are not deduced +// during parsing but during template instantiation instead. + +template +struct x1 { +//CHECK: -CXXMethodDecl {{.*}} operator= 'x1 &(const x1 &){{( __attribute__.*)?}} __generic' +//CHECK: -CXXMethodDecl {{.*}} operator= '__generic x1 &(const __generic x1 &){{( __attribute__.*)?}} __generic' + x1& operator=(const x1& xx) { + y = xx.y; + return *this; + } + int y; +}; + +template +struct x2 { +//CHECK: -CXXMethodDecl {{.*}} foo 'void (x1 *){{( __attribute__.*)?}} __generic' +//CHECK: -CXXMethodDecl {{.*}} foo 'void (__generic x1 *){{( __attribute__.*)?}} __generic' + void foo(x1* xx) { + m[0] = *xx; + } +//CHECK: -FieldDecl {{.*}} m 'x1 [2]' + x1 m[2]; +}; + +void bar(__global x1 *xx, __global x2 *bar) { + bar->foo(xx); +} + +template +class x3 : public T { +public: + //CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &){{( __attribute__.*)?}} __generic' + x3(const x3 &t); +}; +//CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &){{( __attribute__.*)?}} __generic' +template +x3::x3(const x3 &t) {} + +template +T xxx(T *in) { + // This pointer can't be deduced to generic because addr space + // will be taken from the template argument. + //CHECK: `-VarDecl {{.*}} i 'T *' cinit + T *i = in; + T ii; + return *i; +} + +__kernel void test() { + int foo[10]; + xxx(&foo[0]); +} diff --git a/clang/test/SemaOpenCLCXX/address-space-templates.cl b/clang/test/SemaOpenCLCXX/address-space-templates.cl index 48fbdc7642d6fc..3fb935766e9414 100644 --- a/clang/test/SemaOpenCLCXX/address-space-templates.cl +++ b/clang/test/SemaOpenCLCXX/address-space-templates.cl @@ -3,7 +3,7 @@ template struct S { T a; // expected-error{{field may not be qualified with an address space}} - T f1(); // expected-error{{function type may not be qualified with an address space}} + T f1(); // we ignore address space on a return types. void f2(T); // expected-error{{parameter may not be qualified with an address space}} }; diff --git a/clang/test/SemaOpenCLCXX/newdelete.cl b/clang/test/SemaOpenCLCXX/newdelete.cl index 14be4550c0fc63..abc4c0fb6cbd6e 100644 --- a/clang/test/SemaOpenCLCXX/newdelete.cl +++ b/clang/test/SemaOpenCLCXX/newdelete.cl @@ -19,8 +19,8 @@ class B { // There are no global user-defined new operators at this point. Test that clang // rejects these gracefully. void test_default_new_delete(void *buffer, A **pa) { - A *a = new A; // expected-error {{'default new' is not supported in OpenCL C++}} - delete a; // expected-error {{'default delete' is not supported in OpenCL C++}} + A *a = new A; // expected-error {{'default new' is not supported in C++ for OpenCL}} + delete a; // expected-error {{'default delete' is not supported in C++ for OpenCL}} *pa = new (buffer) A; // expected-error {{use of placement new requires explicit declaration}} } @@ -36,10 +36,10 @@ void *operator new[](size_t _s, void *ptr) noexcept { void test_new_delete(void *buffer, A **a, B **b) { *a = new A; // expected-error {{no matching function for call to 'operator new'}} - delete a; // expected-error {{'default delete' is not supported in OpenCL C++}} + delete a; // expected-error {{'default delete' is not supported in C++ for OpenCL}} *a = new A[20]; // expected-error {{no matching function for call to 'operator new[]'}} - delete[] *a; // expected-error {{'default delete' is not supported in OpenCL C++}} + delete[] *a; // expected-error {{'default delete' is not supported in C++ for OpenCL}} // User-defined placement new is supported. *a = new (buffer) A; diff --git a/clang/test/SemaOpenCLCXX/restricted.cl b/clang/test/SemaOpenCLCXX/restricted.cl index f4ad27ad29d938..2af4ae137c41df 100644 --- a/clang/test/SemaOpenCLCXX/restricted.cl +++ b/clang/test/SemaOpenCLCXX/restricted.cl @@ -1,9 +1,9 @@ // RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -verify -fsyntax-only // This test checks that various C/C++/OpenCL C constructs are not available in -// OpenCL C++, according to OpenCL C++ 1.0 Specification Section 2.9. +// C++ for OpenCL. -// Test that typeid is not available in OpenCL C++. +// Test that typeid is not available. namespace std { // Provide a dummy std::type_info so that we can use typeid. class type_info { @@ -11,9 +11,9 @@ namespace std { }; } __constant std::type_info int_ti = typeid(int); -// expected-error@-1 {{'typeid' is not supported in OpenCL C++}} +// expected-error@-1 {{'typeid' is not supported in C++ for OpenCL}} -// Test that dynamic_cast is not available in OpenCL C++. +// Test that dynamic_cast is not available in C++ for OpenCL. class A { public: int a; @@ -25,17 +25,17 @@ class B : public A { B *test_dynamic_cast(B *p) { return dynamic_cast(p); - // expected-error@-1 {{'dynamic_cast' is not supported in OpenCL C++}} + // expected-error@-1 {{'dynamic_cast' is not supported in C++ for OpenCL}} } // Test storage class qualifiers. __constant _Thread_local int a = 1; -// expected-error@-1 {{OpenCL C++ version 1.0 does not support the '_Thread_local' storage class specifier}} +// expected-error@-1 {{C++ for OpenCL version 1.0 does not support the '_Thread_local' storage class specifier}} __constant __thread int b = 2; -// expected-error@-1 {{OpenCL C++ version 1.0 does not support the '__thread' storage class specifier}} +// expected-error@-1 {{C++ for OpenCL version 1.0 does not support the '__thread' storage class specifier}} kernel void test_storage_classes() { register int x; - // expected-error@-1 {{OpenCL C++ version 1.0 does not support the 'register' storage class specifier}} + // expected-error@-1 {{C++ for OpenCL version 1.0 does not support the 'register' storage class specifier}} thread_local int y; - // expected-error@-1 {{OpenCL C++ version 1.0 does not support the 'thread_local' storage class specifier}} + // expected-error@-1 {{C++ for OpenCL version 1.0 does not support the 'thread_local' storage class specifier}} } diff --git a/clang/test/SemaTemplate/instantiate-function-params.cpp b/clang/test/SemaTemplate/instantiate-function-params.cpp index 7984e258653deb..505034d004d196 100644 --- a/clang/test/SemaTemplate/instantiate-function-params.cpp +++ b/clang/test/SemaTemplate/instantiate-function-params.cpp @@ -88,7 +88,7 @@ namespace InstantiateFunctionTypedef { __attribute__((stdcall)) functype stdfunc1; stdfunctype stdfunc2; - __attribute__((pcs("aapcs"))) functype pcsfunc; // expected-warning {{'pcs' calling convention ignored for this target}} + __attribute__((pcs("aapcs"))) functype pcsfunc; // expected-warning {{'pcs' calling convention is not supported for this target}} }; void f(X x) { diff --git a/clang/test/SemaTemplate/typo-variadic.cpp b/clang/test/SemaTemplate/typo-variadic.cpp new file mode 100644 index 00000000000000..c9b777aebbe917 --- /dev/null +++ b/clang/test/SemaTemplate/typo-variadic.cpp @@ -0,0 +1,2 @@ +// RUN: %clang_cc1 -fsyntax-only %s -verify +int x = m(s...); // expected-error{{pack expansion does not}} expected-error{{undeclared identifier}} diff --git a/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp b/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp index d0d35d51e80e5d..ba2dff0af8a932 100644 --- a/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp +++ b/clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp @@ -159,7 +159,6 @@ static void CreateAndRunJITFunc(const std::string &IR, CodeGenOpt::Level OLvl) { builder.setMAttrs(getFeatureList()); builder.setErrorStr(&ErrorMsg); builder.setEngineKind(EngineKind::JIT); - builder.setUseOrcMCJITReplacement(false); builder.setMCJITMemoryManager(make_unique()); builder.setOptLevel(OLvl); builder.setTargetOptions(InitTargetOptionsFromCodeGenFlags()); diff --git a/clang/tools/scan-view/share/ScanView.py b/clang/tools/scan-view/share/ScanView.py index c40366b2e84905..a6cc7692ffe003 100644 --- a/clang/tools/scan-view/share/ScanView.py +++ b/clang/tools/scan-view/share/ScanView.py @@ -764,11 +764,11 @@ def send_patched_file(self, path, ctype): variables['report'] = m.group(2) try: - f = open(path,'r') + f = open(path,'rb') except IOError: return self.send_404() fs = os.fstat(f.fileno()) - data = f.read() + data = f.read().decode('utf-8') for a,b in kReportReplacements: data = a.sub(b % variables, data) return self.send_string(data, ctype, mtime=fs.st_mtime) diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 6b8315f2b9ead4..6ea350cc72657f 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -5122,6 +5122,67 @@ TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) { EXPECT_EQ(ToLSize, FromLSize); } +TEST_P(ASTImporterOptionSpecificTestBase, LambdaInGlobalScope) { + Decl *FromTU = getTuDecl( + R"( + auto l1 = [](unsigned lp) { return 1; }; + auto l2 = [](int lp) { return 2; }; + int f(int p) { + return l1(p) + l2(p); + } + )", + Lang_CXX11, "input0.cc"); + FunctionDecl *FromF = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("f"))); + FunctionDecl *ToF = Import(FromF, Lang_CXX11); + EXPECT_TRUE(ToF); +} + +struct LLDBLookupTest : ASTImporterOptionSpecificTestBase { + LLDBLookupTest() { + Creator = [](ASTContext &ToContext, FileManager &ToFileManager, + ASTContext &FromContext, FileManager &FromFileManager, + bool MinimalImport, + const std::shared_ptr &SharedState) { + return new ASTImporter(ToContext, ToFileManager, FromContext, + FromFileManager, MinimalImport, + // We use the regular lookup. + /*SharedState=*/nullptr); + }; + } +}; + +TEST_P(LLDBLookupTest, ImporterShouldFindInTransparentContext) { + TranslationUnitDecl *ToTU = getToTuDecl( + R"( + extern "C" { + class X{}; + }; + )", + Lang_CXX); + auto *ToX = FirstDeclMatcher().match( + ToTU, cxxRecordDecl(hasName("X"))); + + // Set up a stub external storage. + ToTU->setHasExternalLexicalStorage(true); + // Set up DeclContextBits.HasLazyExternalLexicalLookups to true. + ToTU->setMustBuildLookupTable(); + struct TestExternalASTSource : ExternalASTSource {}; + ToTU->getASTContext().setExternalSource(new TestExternalASTSource()); + + Decl *FromTU = getTuDecl( + R"( + class X; + )", + Lang_CXX); + auto *FromX = FirstDeclMatcher().match( + FromTU, cxxRecordDecl(hasName("X"))); + auto *ImportedX = Import(FromX, Lang_CXX); + // The lookup must find the existing class definition in the LinkageSpecDecl. + // Then the importer renders the existing and the new decl into one chain. + EXPECT_EQ(ImportedX->getCanonicalDecl(), ToX->getCanonicalDecl()); +} + INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest, DefaultTestValuesForRunOptions, ); @@ -5168,5 +5229,8 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods, INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables, DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, LLDBLookupTest, + DefaultTestValuesForRunOptions, ); + } // end namespace ast_matchers } // end namespace clang diff --git a/clang/unittests/AST/ASTImporterVisibilityTest.cpp b/clang/unittests/AST/ASTImporterVisibilityTest.cpp index 66c967e8460b93..88543257b75a47 100644 --- a/clang/unittests/AST/ASTImporterVisibilityTest.cpp +++ b/clang/unittests/AST/ASTImporterVisibilityTest.cpp @@ -80,13 +80,13 @@ class ImportVisibilityChain std::string Code = getCode() + getCode(); auto Pattern = getPattern(); - TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_CXX, "input0.cc"); + TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_CXX14, "input0.cc"); auto *FromD0 = FirstDeclMatcher().match(FromTu, Pattern); auto *FromD1 = LastDeclMatcher().match(FromTu, Pattern); - auto *ToD0 = Import(FromD0, Lang_CXX); - auto *ToD1 = Import(FromD1, Lang_CXX); + auto *ToD0 = Import(FromD0, Lang_CXX14); + auto *ToD1 = Import(FromD1, Lang_CXX14); EXPECT_TRUE(ToD0); ASSERT_TRUE(ToD1); @@ -157,13 +157,14 @@ class ImportVisibility BindableMatcher getPattern() const { return PatternFactory()(); } void TypedTest_ImportAfter() { - TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX); - TranslationUnitDecl *FromTu = getTuDecl(getCode1(), Lang_CXX, "input1.cc"); + TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX14); + TranslationUnitDecl *FromTu = + getTuDecl(getCode1(), Lang_CXX14, "input1.cc"); auto *ToD0 = FirstDeclMatcher().match(ToTu, getPattern()); auto *FromD1 = FirstDeclMatcher().match(FromTu, getPattern()); - auto *ToD1 = Import(FromD1, Lang_CXX); + auto *ToD1 = Import(FromD1, Lang_CXX14); ASSERT_TRUE(ToD0); ASSERT_TRUE(ToD1); @@ -176,12 +177,14 @@ class ImportVisibility } void TypedTest_ImportAfterImport() { - TranslationUnitDecl *FromTu0 = getTuDecl(getCode0(), Lang_CXX, "input0.cc"); - TranslationUnitDecl *FromTu1 = getTuDecl(getCode1(), Lang_CXX, "input1.cc"); + TranslationUnitDecl *FromTu0 = + getTuDecl(getCode0(), Lang_CXX14, "input0.cc"); + TranslationUnitDecl *FromTu1 = + getTuDecl(getCode1(), Lang_CXX14, "input1.cc"); auto *FromD0 = FirstDeclMatcher().match(FromTu0, getPattern()); auto *FromD1 = FirstDeclMatcher().match(FromTu1, getPattern()); - auto *ToD0 = Import(FromD0, Lang_CXX); - auto *ToD1 = Import(FromD1, Lang_CXX); + auto *ToD0 = Import(FromD0, Lang_CXX14); + auto *ToD1 = Import(FromD1, Lang_CXX14); ASSERT_TRUE(ToD0); ASSERT_TRUE(ToD1); EXPECT_NE(ToD0, ToD1); @@ -192,13 +195,14 @@ class ImportVisibility } void TypedTest_ImportAfterWithMerge() { - TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX); - TranslationUnitDecl *FromTu = getTuDecl(getCode1(), Lang_CXX, "input1.cc"); + TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX14); + TranslationUnitDecl *FromTu = + getTuDecl(getCode1(), Lang_CXX14, "input1.cc"); auto *ToF0 = FirstDeclMatcher().match(ToTu, getPattern()); auto *FromF1 = FirstDeclMatcher().match(FromTu, getPattern()); - auto *ToF1 = Import(FromF1, Lang_CXX); + auto *ToF1 = Import(FromF1, Lang_CXX14); ASSERT_TRUE(ToF0); ASSERT_TRUE(ToF1); @@ -213,12 +217,14 @@ class ImportVisibility } void TypedTest_ImportAfterImportWithMerge() { - TranslationUnitDecl *FromTu0 = getTuDecl(getCode0(), Lang_CXX, "input0.cc"); - TranslationUnitDecl *FromTu1 = getTuDecl(getCode1(), Lang_CXX, "input1.cc"); + TranslationUnitDecl *FromTu0 = + getTuDecl(getCode0(), Lang_CXX14, "input0.cc"); + TranslationUnitDecl *FromTu1 = + getTuDecl(getCode1(), Lang_CXX14, "input1.cc"); auto *FromF0 = FirstDeclMatcher().match(FromTu0, getPattern()); auto *FromF1 = FirstDeclMatcher().match(FromTu1, getPattern()); - auto *ToF0 = Import(FromF0, Lang_CXX); - auto *ToF1 = Import(FromF1, Lang_CXX); + auto *ToF0 = Import(FromF0, Lang_CXX14); + auto *ToF1 = Import(FromF1, Lang_CXX14); ASSERT_TRUE(ToF0); ASSERT_TRUE(ToF1); if (shouldBeLinked()) diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp index 63757987e113c6..cdb55d90b9dfbe 100644 --- a/clang/unittests/AST/StructuralEquivalenceTest.cpp +++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp @@ -797,6 +797,58 @@ TEST_F(StructuralEquivalenceRecordTest, RecordsWithDifferentBody) { EXPECT_FALSE(testStructuralMatch(t)); } +struct StructuralEquivalenceLambdaTest : StructuralEquivalenceTest {}; + +TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentMethods) { + // Get the LambdaExprs, unfortunately we can't match directly the underlying + // implicit CXXRecordDecl of the Lambda classes. + auto t = makeDecls( + "void f() { auto L0 = [](int){}; }", + "void f() { auto L1 = [](){}; }", + Lang_CXX11, + lambdaExpr(), + lambdaExpr()); + CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); + CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); + EXPECT_FALSE(testStructuralMatch(L0, L1)); +} + +TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqMethods) { + auto t = makeDecls( + "void f() { auto L0 = [](int){}; }", + "void f() { auto L1 = [](int){}; }", + Lang_CXX11, + lambdaExpr(), + lambdaExpr()); + CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); + CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); + EXPECT_TRUE(testStructuralMatch(L0, L1)); +} + +TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentFields) { + auto t = makeDecls( + "void f() { char* X; auto L0 = [X](){}; }", + "void f() { float X; auto L1 = [X](){}; }", + Lang_CXX11, + lambdaExpr(), + lambdaExpr()); + CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); + CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); + EXPECT_FALSE(testStructuralMatch(L0, L1)); +} + +TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqFields) { + auto t = makeDecls( + "void f() { float X; auto L0 = [X](){}; }", + "void f() { float X; auto L1 = [X](){}; }", + Lang_CXX11, + lambdaExpr(), + lambdaExpr()); + CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); + CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); + EXPECT_TRUE(testStructuralMatch(L0, L1)); +} + TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) { auto t = makeNamedDecls( "struct A{ }; struct B{ }; void foo(A a, A b);", diff --git a/clang/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp b/clang/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp index a2c50fc7d000f8..a6b48e56236756 100644 --- a/clang/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp +++ b/clang/unittests/DirectoryWatcher/DirectoryWatcherTest.cpp @@ -32,18 +32,26 @@ static bool operator==(const DirectoryWatcher::Event &lhs, namespace { +typedef DirectoryWatcher::Event::EventKind EventKind; + struct DirectoryWatcherTestFixture { std::string TestRootDir; std::string TestWatchedDir; DirectoryWatcherTestFixture() { SmallString<128> pathBuf; - std::error_code UniqDirRes = createUniqueDirectory("dirwatcher", pathBuf); +#ifndef NDEBUG + std::error_code UniqDirRes = +#endif + createUniqueDirectory("dirwatcher", pathBuf); assert(!UniqDirRes); TestRootDir = pathBuf.str(); path::append(pathBuf, "watch"); TestWatchedDir = pathBuf.str(); - std::error_code CreateDirRes = create_directory(TestWatchedDir, false); +#ifndef NDEBUG + std::error_code CreateDirRes = +#endif + create_directory(TestWatchedDir, false); assert(!CreateDirRes); } @@ -75,15 +83,15 @@ struct DirectoryWatcherTestFixture { } }; -std::string eventKindToString(const DirectoryWatcher::Event::EventKind K) { +std::string eventKindToString(const EventKind K) { switch (K) { - case DirectoryWatcher::Event::EventKind::Removed: + case EventKind::Removed: return "Removed"; - case DirectoryWatcher::Event::EventKind::Modified: + case EventKind::Modified: return "Modified"; - case DirectoryWatcher::Event::EventKind::WatchedDirRemoved: + case EventKind::WatchedDirRemoved: return "WatchedDirRemoved"; - case DirectoryWatcher::Event::EventKind::WatcherGotInvalidated: + case EventKind::WatcherGotInvalidated: return "WatcherGotInvalidated"; } llvm_unreachable("unknown event kind"); @@ -91,7 +99,9 @@ std::string eventKindToString(const DirectoryWatcher::Event::EventKind K) { struct VerifyingConsumer { std::vector ExpectedInitial; + const std::vector ExpectedInitialCopy; std::vector ExpectedNonInitial; + const std::vector ExpectedNonInitialCopy; std::vector OptionalNonInitial; std::vector UnexpectedInitial; std::vector UnexpectedNonInitial; @@ -102,8 +112,8 @@ struct VerifyingConsumer { const std::vector &ExpectedInitial, const std::vector &ExpectedNonInitial, const std::vector &OptionalNonInitial = {}) - : ExpectedInitial(ExpectedInitial), - ExpectedNonInitial(ExpectedNonInitial), + : ExpectedInitial(ExpectedInitial), ExpectedInitialCopy(ExpectedInitial), + ExpectedNonInitial(ExpectedNonInitial), ExpectedNonInitialCopy(ExpectedNonInitial), OptionalNonInitial(OptionalNonInitial) {} // This method is used by DirectoryWatcher. @@ -175,6 +185,26 @@ struct VerifyingConsumer { } void printUnmetExpectations(llvm::raw_ostream &OS) { + // If there was any issue, print the expected state + if ( + !ExpectedInitial.empty() + || + !ExpectedNonInitial.empty() + || + !UnexpectedInitial.empty() + || + !UnexpectedNonInitial.empty() + ) { + OS << "Expected initial events: \n"; + for (const auto &E : ExpectedInitialCopy) { + OS << eventKindToString(E.Kind) << " " << E.Filename << "\n"; + } + OS << "Expected non-initial events: \n"; + for (const auto &E : ExpectedNonInitialCopy) { + OS << eventKindToString(E.Kind) << " " << E.Filename << "\n"; + } + } + if (!ExpectedInitial.empty()) { OS << "Expected but not seen initial events: \n"; for (const auto &E : ExpectedInitial) { @@ -212,6 +242,7 @@ void checkEventualResultWithTimeout(VerifyingConsumer &TestConsumer) { EXPECT_TRUE(WaitForExpectedStateResult.wait_for(std::chrono::seconds(3)) == std::future_status::ready) << "The expected result state wasn't reached before the time-out."; + std::unique_lock L(TestConsumer.Mtx); EXPECT_TRUE(TestConsumer.result().hasValue()); if (TestConsumer.result().hasValue()) { EXPECT_TRUE(*TestConsumer.result()); @@ -220,7 +251,6 @@ void checkEventualResultWithTimeout(VerifyingConsumer &TestConsumer) { !TestConsumer.result().hasValue()) TestConsumer.printUnmetExpectations(llvm::outs()); } - } // namespace TEST(DirectoryWatcherTest, InitialScanSync) { @@ -231,10 +261,17 @@ TEST(DirectoryWatcherTest, InitialScanSync) { fixture.addFile("c"); VerifyingConsumer TestConsumer{ - {{DirectoryWatcher::Event::EventKind::Modified, "a"}, - {DirectoryWatcher::Event::EventKind::Modified, "b"}, - {DirectoryWatcher::Event::EventKind::Modified, "c"}}, - {}}; + {{EventKind::Modified, "a"}, + {EventKind::Modified, "b"}, + {EventKind::Modified, "c"}}, + {}, + // We have to ignore these as it's a race between the test process + // which is scanning the directory and kernel which is sending + // notification. + {{EventKind::Modified, "a"}, + {EventKind::Modified, "b"}, + {EventKind::Modified, "c"}} + }; auto DW = DirectoryWatcher::create( fixture.TestWatchedDir, @@ -255,10 +292,17 @@ TEST(DirectoryWatcherTest, InitialScanAsync) { fixture.addFile("c"); VerifyingConsumer TestConsumer{ - {{DirectoryWatcher::Event::EventKind::Modified, "a"}, - {DirectoryWatcher::Event::EventKind::Modified, "b"}, - {DirectoryWatcher::Event::EventKind::Modified, "c"}}, - {}}; + {{EventKind::Modified, "a"}, + {EventKind::Modified, "b"}, + {EventKind::Modified, "c"}}, + {}, + // We have to ignore these as it's a race between the test process + // which is scanning the directory and kernel which is sending + // notification. + {{EventKind::Modified, "a"}, + {EventKind::Modified, "b"}, + {EventKind::Modified, "c"}} + }; auto DW = DirectoryWatcher::create( fixture.TestWatchedDir, @@ -276,9 +320,9 @@ TEST(DirectoryWatcherTest, AddFiles) { VerifyingConsumer TestConsumer{ {}, - {{DirectoryWatcher::Event::EventKind::Modified, "a"}, - {DirectoryWatcher::Event::EventKind::Modified, "b"}, - {DirectoryWatcher::Event::EventKind::Modified, "c"}}}; + {{EventKind::Modified, "a"}, + {EventKind::Modified, "b"}, + {EventKind::Modified, "c"}}}; auto DW = DirectoryWatcher::create( fixture.TestWatchedDir, @@ -301,8 +345,9 @@ TEST(DirectoryWatcherTest, ModifyFile) { fixture.addFile("a"); VerifyingConsumer TestConsumer{ - {{DirectoryWatcher::Event::EventKind::Modified, "a"}}, - {{DirectoryWatcher::Event::EventKind::Modified, "a"}}}; + {{EventKind::Modified, "a"}}, + {{EventKind::Modified, "a"}}, + {{EventKind::Modified, "a"}}}; auto DW = DirectoryWatcher::create( fixture.TestWatchedDir, @@ -330,8 +375,9 @@ TEST(DirectoryWatcherTest, DeleteFile) { fixture.addFile("a"); VerifyingConsumer TestConsumer{ - {{DirectoryWatcher::Event::EventKind::Modified, "a"}}, - {{DirectoryWatcher::Event::EventKind::Removed, "a"}}}; + {{EventKind::Modified, "a"}}, + {{EventKind::Removed, "a"}}, + {{EventKind::Modified, "a"}}}; auto DW = DirectoryWatcher::create( fixture.TestWatchedDir, @@ -351,8 +397,8 @@ TEST(DirectoryWatcherTest, DeleteWatchedDir) { VerifyingConsumer TestConsumer{ {}, - {{DirectoryWatcher::Event::EventKind::WatchedDirRemoved, ""}, - {DirectoryWatcher::Event::EventKind::WatcherGotInvalidated, ""}}}; + {{EventKind::WatchedDirRemoved, ""}, + {EventKind::WatcherGotInvalidated, ""}}}; auto DW = DirectoryWatcher::create( fixture.TestWatchedDir, @@ -371,7 +417,7 @@ TEST(DirectoryWatcherTest, InvalidatedWatcher) { DirectoryWatcherTestFixture fixture; VerifyingConsumer TestConsumer{ - {}, {{DirectoryWatcher::Event::EventKind::WatcherGotInvalidated, ""}}}; + {}, {{EventKind::WatcherGotInvalidated, ""}}}; { auto DW = DirectoryWatcher::create( @@ -384,43 +430,4 @@ TEST(DirectoryWatcherTest, InvalidatedWatcher) { } // DW is destructed here. checkEventualResultWithTimeout(TestConsumer); -} - -TEST(DirectoryWatcherTest, ChangeMetadata) { - DirectoryWatcherTestFixture fixture; - fixture.addFile("a"); - - VerifyingConsumer TestConsumer{ - {{DirectoryWatcher::Event::EventKind::Modified, "a"}}, - // We don't expect any notification for file having access file changed. - {}, - // Given the timing we are ok with receiving the duplicate event. - {{DirectoryWatcher::Event::EventKind::Modified, "a"}}}; - - auto DW = DirectoryWatcher::create( - fixture.TestWatchedDir, - [&TestConsumer](llvm::ArrayRef Events, - bool IsInitial) { - TestConsumer.consume(Events, IsInitial); - }, - /*waitForInitialSync=*/true); - - { // Change access and modification time of file a. - Expected HopefullyTheFD = llvm::sys::fs::openNativeFileForWrite( - fixture.getPathInWatched("a"), CD_OpenExisting, OF_None); - if (!HopefullyTheFD) { - llvm::outs() << HopefullyTheFD.takeError(); - } - - const int FD = HopefullyTheFD.get(); - const TimePoint<> NewTimePt = - std::chrono::system_clock::now() - std::chrono::minutes(1); - - std::error_code setTimeRes = - llvm::sys::fs::setLastAccessAndModificationTime(FD, NewTimePt, - NewTimePt); - assert(!setTimeRes); - } - - checkEventualResultWithTimeout(TestConsumer); -} +} \ No newline at end of file diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index c4abad228d0a33..c1cec110137bd2 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -7027,6 +7027,12 @@ TEST_F(FormatTest, UnderstandsSquareAttributes) { // On the other hand, we still need to correctly find array subscripts. verifyFormat("int a = std::vector{1, 2, 3}[0];"); + // Make sure that we do not mistake Objective-C method inside array literals + // as attributes, even if those method names are also keywords. + verifyFormat("@[ [foo bar] ];"); + verifyFormat("@[ [NSArray class] ];"); + verifyFormat("@[ [foo enum] ];"); + // Make sure we do not parse attributes as lambda introducers. FormatStyle MultiLineFunctions = getLLVMStyle(); MultiLineFunctions.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; diff --git a/clang/unittests/Tooling/CompilationDatabaseTest.cpp b/clang/unittests/Tooling/CompilationDatabaseTest.cpp index da7ae09917dfac..fde95445bdab04 100644 --- a/clang/unittests/Tooling/CompilationDatabaseTest.cpp +++ b/clang/unittests/Tooling/CompilationDatabaseTest.cpp @@ -370,6 +370,33 @@ TEST(findCompileArgsInJsonDatabase, FindsEntry) { EXPECT_EQ("command4", FoundCommand.CommandLine[0]) << ErrorMessage; } +TEST(findCompileArgsInJsonDatabase, ParsesCompilerWrappers) { + StringRef Directory("//net/dir"); + StringRef FileName("//net/dir/filename"); + std::vector> Cases = { + {"distcc gcc foo.c", "gcc foo.c"}, + {"gomacc clang++ foo.c", "clang++ foo.c"}, + {"ccache gcc foo.c", "gcc foo.c"}, + {"ccache.exe gcc foo.c", "gcc foo.c"}, + {"ccache g++.exe foo.c", "g++.exe foo.c"}, + {"ccache distcc gcc foo.c", "gcc foo.c"}, + + {"distcc foo.c", "distcc foo.c"}, + {"distcc -I/foo/bar foo.c", "distcc -I/foo/bar foo.c"}, + }; + std::string ErrorMessage; + + for (const auto &Case : Cases) { + std::string DB = + R"([{"directory":"//net/dir", "file":"//net/dir/foo.c", "command":")" + + Case.first + "\"}]"; + CompileCommand FoundCommand = + findCompileArgsInJsonDatabase("//net/dir/foo.c", DB, ErrorMessage); + EXPECT_EQ(Case.second, llvm::join(FoundCommand.CommandLine, " ")) + << Case.first; + } +} + static std::vector unescapeJsonCommandLine(StringRef Command) { std::string JsonDatabase = ("[{\"directory\":\"//net/root\", \"file\":\"test\", \"command\": \"" + diff --git a/clang/utils/ClangVisualizers/clang.natvis b/clang/utils/ClangVisualizers/clang.natvis index 42b674e7d7bb26..8b2bf49b41bb97 100644 --- a/clang/utils/ClangVisualizers/clang.natvis +++ b/clang/utils/ClangVisualizers/clang.natvis @@ -196,7 +196,11 @@ For later versions of Visual Studio, no setup is required--> (not yet known if parameter pack) ... - {*this,view(TorC)} {*this,view(MaybeEllipses)}{Name,view(cpp)} + {(TypeSourceInfo *)(DefaultArgument.ValueOrInherited.Val.Value&~3LL),view(cpp)} + {{InheritedInitializer}} + = {this,view(DefaultArg)na} + + {*this,view(TorC)} {*this,view(MaybeEllipses)}{Name,view(cpp)} {this,view(Initializer)na} template{TemplateParams,na} {*TemplatedDecl}; @@ -288,7 +292,7 @@ For later versions of Visual Studio, no setup is required--> - {*Replaced,view(cpp)} <= {CanonicalType,view(cpp)} + {{{*Replaced,view(cpp)} <= {CanonicalType,view(cpp)}}} *(clang::Type *)this, view(cmn) *Replaced @@ -353,7 +357,7 @@ For later versions of Visual Studio, no setup is required--> - {InjectedType,view(cpp)} + {Decl,view(cpp)} Decl InjectedType @@ -424,12 +428,21 @@ For later versions of Visual Studio, no setup is required--> Ty - - {Argument} + + {(QualType *)&Ty,na} - Argument + (QualType *)&Ty + Data + + Not building anything + Building a {LastTy} + + + {Argument,view(cpp)} + {Argument} + {*(clang::QualType *)&TypeOrValue.V,view(cpp)} {(clang::TemplateArgument::ArgKind)TypeOrValue.Kind,en} template argument: {*(clang::QualType *)&TypeOrValue.V} @@ -459,6 +472,21 @@ For later versions of Visual Studio, no setup is required--> + + + {((TemplateArgumentLoc*)Arguments.BeginX)[0],view(cpp)}{*this,view(elt1)} + + , {((TemplateArgumentLoc*)Arguments.BeginX)[1],view(cpp)}{*this,view(elt2)} + + , {((TemplateArgumentLoc*)Arguments.BeginX)[2],view(cpp)}{*this,view(elt3)} + + , {((TemplateArgumentLoc*)Arguments.BeginX)[3],view(cpp)}{*this,view(elt4)} + + , ... + empty + <{*this,view(elt0)}> + Uninitialized + {Arguments[0],view(cpp)}{*this,view(arg1)} @@ -483,6 +511,17 @@ For later versions of Visual Studio, no setup is required--> , {Data[2],view(cpp)}, ... <{*this,view(arg0)}> + + Length + + + + Length + Data + + + + @@ -558,6 +597,7 @@ For later versions of Visual Studio, no setup is required--> TemplateSpecializationTypeBits.NumArgs (clang::TemplateArgument *)(this+1) + *(clang::Type *)this, view(cmn) @@ -745,7 +785,7 @@ For later versions of Visual Studio, no setup is required--> {this,view(retType)nand} {Name,view(cpp)nd}({*this,view(parm0)nd}) (clang::DeclaratorDecl *)this,nd - *this,view(retType)nd + ((clang::FunctionProtoType *)((clang::ExtQualsTypeCommonBase *)(((uintptr_t)DeclType.Value.Value) & ~15))->BaseType)->ResultType {*this,view(parm0)nd} @@ -755,6 +795,7 @@ For later versions of Visual Studio, no setup is required--> + TemplateOrSpecialization diff --git a/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp b/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp index 1e495039c494c8..8d83b1c7fa6b93 100644 --- a/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp +++ b/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp @@ -207,7 +207,7 @@ void BuiltinNameEmitter::GetOverloads() { } void BuiltinNameEmitter::EmitSignatureTable() { - OS << "OpenCLType OpenCLSignature[] = {\n"; + OS << "static const OpenCLType OpenCLSignature[] = {\n"; for (auto &P : SignatureSet) { OS << "// " << P.second << "\n"; for (Record *R : P.first) { @@ -222,7 +222,7 @@ void BuiltinNameEmitter::EmitSignatureTable() { } void BuiltinNameEmitter::EmitBuiltinTable() { - OS << "OpenCLBuiltinDecl OpenCLBuiltins[] = {\n"; + OS << "static const OpenCLBuiltinDecl OpenCLBuiltins[] = {\n"; for (auto &i : OverloadInfo) { StringRef Name = i.first; OS << "// " << Name << "\n"; @@ -255,7 +255,7 @@ void BuiltinNameEmitter::EmitStringMatcher() { OS << R"( // Return 0 if name is not a recognized OpenCL builtin, or an index // into a table of declarations if it is an OpenCL builtin. -std::pair isOpenCLBuiltin(llvm::StringRef name) { +static std::pair isOpenCLBuiltin(llvm::StringRef name) { )"; diff --git a/clang/utils/builtin-defines.c b/clang/utils/builtin-defines.c index 2936d631e61a7b..9bbe5be2502697 100644 --- a/clang/utils/builtin-defines.c +++ b/clang/utils/builtin-defines.c @@ -49,6 +49,7 @@ RUN: done; #undef __INT8_TYPE__ #undef __SSP__ #undef __APPLE_CC__ +#undef __VERSION__ #undef __clang__ #undef __llvm__ #undef __nocona diff --git a/clang/utils/perf-training/lit.cfg b/clang/utils/perf-training/lit.cfg index 671d44f83b9485..be822d66e38ce4 100644 --- a/clang/utils/perf-training/lit.cfg +++ b/clang/utils/perf-training/lit.cfg @@ -10,7 +10,7 @@ def getSysrootFlagsOnDarwin(config, lit_config): # default system root path. if 'darwin' in config.target_triple: try: - out = subprocess.check_output(['xcrun', '--show-sdk-path']).strip() + out = subprocess.check_output(['xcrun', '--show-sdk-path']).strip().decode() res = 0 except OSError: res = -1 diff --git a/compiler-rt/lib/asan/asan_malloc_win.cc b/compiler-rt/lib/asan/asan_malloc_win.cc index 89d70034092619..5fad55d6e28408 100644 --- a/compiler-rt/lib/asan/asan_malloc_win.cc +++ b/compiler-rt/lib/asan/asan_malloc_win.cc @@ -14,17 +14,12 @@ #include "sanitizer_common/sanitizer_allocator_interface.h" #include "sanitizer_common/sanitizer_platform.h" #if SANITIZER_WINDOWS -// Need to include defintions for windows heap api functions, -// these assume windows.h will also be included. This definition -// fixes an error that's thrown if you only include heapapi.h -#if defined(_M_IX86) -#define _X86_ -#elif defined(_M_AMD64) -#define _AMD64_ -#else -#error "Missing arch or unsupported platform for Windows." -#endif -#include +#include "asan_allocator.h" +#include "asan_interceptors.h" +#include "asan_internal.h" +#include "asan_stack.h" +#include "interception/interception.h" +#include // Intentionally not including windows.h here, to avoid the risk of // pulling in conflicting declarations of these functions. (With mingw-w64, @@ -34,6 +29,9 @@ typedef void *HANDLE; typedef const void *LPCVOID; typedef void *LPVOID; +typedef unsigned long DWORD; +constexpr unsigned long HEAP_ZERO_MEMORY = 0x00000008; +constexpr unsigned long HEAP_REALLOC_IN_PLACE_ONLY = 0x00000010; constexpr unsigned long HEAP_ALLOCATE_SUPPORTED_FLAGS = (HEAP_ZERO_MEMORY); constexpr unsigned long HEAP_ALLOCATE_UNSUPPORTED_FLAGS = (~HEAP_ALLOCATE_SUPPORTED_FLAGS); @@ -45,13 +43,16 @@ constexpr unsigned long HEAP_REALLOC_SUPPORTED_FLAGS = constexpr unsigned long HEAP_REALLOC_UNSUPPORTED_FLAGS = (~HEAP_ALLOCATE_SUPPORTED_FLAGS); -#include "asan_allocator.h" -#include "asan_interceptors.h" -#include "asan_internal.h" -#include "asan_stack.h" -#include "interception/interception.h" -#include +extern "C" { +LPVOID WINAPI HeapAlloc(HANDLE hHeap, DWORD dwFlags, size_t dwBytes); +LPVOID WINAPI HeapReAlloc(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, + size_t dwBytes); +BOOL WINAPI HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem); +size_t WINAPI HeapSize(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem); + +BOOL WINAPI HeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem); +} using namespace __asan; // NOLINT @@ -160,7 +161,7 @@ void *_recalloc(void *p, size_t n, size_t elem_size) { size_t old_size = _msize(p); void *new_alloc = malloc(size); if (new_alloc) { - REAL(memcpy)(new_alloc, p, Min(size, old_size)); + REAL(memcpy)(new_alloc, p, Min(size, old_size)); if (old_size < size) REAL(memset)(((u8 *)new_alloc) + old_size, 0, size - old_size); free(p); @@ -206,7 +207,7 @@ int _CrtSetReportMode(int, int) { #define OWNED_BY_RTL(heap, memory) \ (!__sanitizer_get_ownership(memory) && HeapValidate(heap, 0, memory)) -INTERCEPTOR_WINAPI(SIZE_T, HeapSize, HANDLE hHeap, DWORD dwFlags, +INTERCEPTOR_WINAPI(size_t, HeapSize, HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem) { // If the RTL allocators are hooked we need to check whether the ASAN // allocator owns the pointer we're about to use. Allocations occur before @@ -224,7 +225,7 @@ INTERCEPTOR_WINAPI(SIZE_T, HeapSize, HANDLE hHeap, DWORD dwFlags, } INTERCEPTOR_WINAPI(LPVOID, HeapAlloc, HANDLE hHeap, DWORD dwFlags, - SIZE_T dwBytes) { + size_t dwBytes) { // If the ASAN runtime is not initialized, or we encounter an unsupported // flag, fall back to the original allocator. if (flags()->windows_hook_rtl_allocators) { @@ -269,14 +270,14 @@ INTERCEPTOR_WINAPI(BOOL, HeapFree, HANDLE hHeap, DWORD dwFlags, LPVOID lpMem) { } namespace __asan { -using AllocFunction = LPVOID(WINAPI *)(HANDLE, DWORD, SIZE_T); -using ReAllocFunction = LPVOID(WINAPI *)(HANDLE, DWORD, LPVOID, SIZE_T); -using SizeFunction = SIZE_T(WINAPI *)(HANDLE, DWORD, LPVOID); +using AllocFunction = LPVOID(WINAPI *)(HANDLE, DWORD, size_t); +using ReAllocFunction = LPVOID(WINAPI *)(HANDLE, DWORD, LPVOID, size_t); +using SizeFunction = size_t(WINAPI *)(HANDLE, DWORD, LPVOID); using FreeFunction = BOOL(WINAPI *)(HANDLE, DWORD, LPVOID); void *SharedReAlloc(ReAllocFunction reallocFunc, SizeFunction heapSizeFunc, FreeFunction freeFunc, AllocFunction allocFunc, - HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes) { + HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, size_t dwBytes) { CHECK(reallocFunc && heapSizeFunc && freeFunc && allocFunc); GET_STACK_TRACE_MALLOC; GET_CURRENT_PC_BP_SP; @@ -317,7 +318,7 @@ void *SharedReAlloc(ReAllocFunction reallocFunc, SizeFunction heapSizeFunc, replacement_alloc = asan_malloc(dwBytes, &stack); if (replacement_alloc) { size_t old_size = heapSizeFunc(hHeap, dwFlags, lpMem); - if (old_size == ((SIZE_T)0) - 1) { + if (old_size == ((size_t)0) - 1) { asan_free(replacement_alloc, &stack, FROM_MALLOC); return nullptr; } @@ -341,7 +342,8 @@ void *SharedReAlloc(ReAllocFunction reallocFunc, SizeFunction heapSizeFunc, size_t old_usable_size = 0; if (replacement_alloc) { old_usable_size = asan_malloc_usable_size(lpMem, pc, bp); - REAL(memcpy)(replacement_alloc, lpMem, min(dwBytes, old_usable_size)); + REAL(memcpy)(replacement_alloc, lpMem, + Min(dwBytes, old_usable_size)); asan_free(lpMem, &stack, FROM_MALLOC); } return replacement_alloc; @@ -388,7 +390,7 @@ void *SharedReAlloc(ReAllocFunction reallocFunc, SizeFunction heapSizeFunc, } // namespace __asan INTERCEPTOR_WINAPI(LPVOID, HeapReAlloc, HANDLE hHeap, DWORD dwFlags, - LPVOID lpMem, SIZE_T dwBytes) { + LPVOID lpMem, size_t dwBytes) { return SharedReAlloc(REAL(HeapReAlloc), (SizeFunction)REAL(HeapSize), REAL(HeapFree), REAL(HeapAlloc), hHeap, dwFlags, lpMem, dwBytes); @@ -399,28 +401,27 @@ INTERCEPTOR_WINAPI(LPVOID, HeapReAlloc, HANDLE hHeap, DWORD dwFlags, // allocations with detours and their definitions are unlikely to change. // Comments in /minkernel/ntos/rtl/heappublic.c indicate that these functions // are part of the heap's public interface. -typedef ULONG LOGICAL; +typedef unsigned long LOGICAL; // This function is documented as part of the Driver Development Kit but *not* // the Windows Development Kit. -NTSYSAPI LOGICAL RtlFreeHeap(PVOID HeapHandle, ULONG Flags, - _Frees_ptr_opt_ PVOID BaseAddress); +LOGICAL RtlFreeHeap(void* HeapHandle, DWORD Flags, + void* BaseAddress); // This function is documented as part of the Driver Development Kit but *not* // the Windows Development Kit. -NTSYSAPI PVOID RtlAllocateHeap(PVOID HeapHandle, ULONG Flags, SIZE_T Size); +void* RtlAllocateHeap(void* HeapHandle, DWORD Flags, size_t Size); // This function is completely undocumented. -PVOID -RtlReAllocateHeap(PVOID HeapHandle, ULONG Flags, PVOID BaseAddress, - SIZE_T Size); +void* +RtlReAllocateHeap(void* HeapHandle, DWORD Flags, void* BaseAddress, + size_t Size); // This function is completely undocumented. -SIZE_T -RtlSizeHeap(PVOID HeapHandle, ULONG Flags, PVOID BaseAddress); +size_t RtlSizeHeap(void* HeapHandle, DWORD Flags, void* BaseAddress); -INTERCEPTOR_WINAPI(SIZE_T, RtlSizeHeap, HANDLE HeapHandle, ULONG Flags, - PVOID BaseAddress) { +INTERCEPTOR_WINAPI(size_t, RtlSizeHeap, HANDLE HeapHandle, DWORD Flags, + void* BaseAddress) { if (!flags()->windows_hook_rtl_allocators || UNLIKELY(!asan_inited || OWNED_BY_RTL(HeapHandle, BaseAddress))) { return REAL(RtlSizeHeap)(HeapHandle, Flags, BaseAddress); @@ -430,8 +431,8 @@ INTERCEPTOR_WINAPI(SIZE_T, RtlSizeHeap, HANDLE HeapHandle, ULONG Flags, return asan_malloc_usable_size(BaseAddress, pc, bp); } -INTERCEPTOR_WINAPI(BOOL, RtlFreeHeap, HANDLE HeapHandle, ULONG Flags, - PVOID BaseAddress) { +INTERCEPTOR_WINAPI(BOOL, RtlFreeHeap, HANDLE HeapHandle, DWORD Flags, + void* BaseAddress) { // Heap allocations happen before this function is hooked, so we must fall // back to the original function if the pointer is not from the ASAN heap, or // unsupported flags are provided. @@ -445,8 +446,8 @@ INTERCEPTOR_WINAPI(BOOL, RtlFreeHeap, HANDLE HeapHandle, ULONG Flags, return true; } -INTERCEPTOR_WINAPI(PVOID, RtlAllocateHeap, HANDLE HeapHandle, DWORD Flags, - SIZE_T Size) { +INTERCEPTOR_WINAPI(void*, RtlAllocateHeap, HANDLE HeapHandle, DWORD Flags, + size_t Size) { // If the ASAN runtime is not initialized, or we encounter an unsupported // flag, fall back to the original allocator. if (!flags()->windows_hook_rtl_allocators || @@ -467,8 +468,8 @@ INTERCEPTOR_WINAPI(PVOID, RtlAllocateHeap, HANDLE HeapHandle, DWORD Flags, return p; } -INTERCEPTOR_WINAPI(PVOID, RtlReAllocateHeap, HANDLE HeapHandle, ULONG Flags, - PVOID BaseAddress, SIZE_T Size) { +INTERCEPTOR_WINAPI(void*, RtlReAllocateHeap, HANDLE HeapHandle, DWORD Flags, + void* BaseAddress, size_t Size) { // If it's actually a heap block which was allocated before the ASAN runtime // came up, use the real RtlFreeHeap function. if (!flags()->windows_hook_rtl_allocators) diff --git a/compiler-rt/lib/gwp_asan/CMakeLists.txt b/compiler-rt/lib/gwp_asan/CMakeLists.txt index 952acb1830411f..94c5336ce1b3bd 100644 --- a/compiler-rt/lib/gwp_asan/CMakeLists.txt +++ b/compiler-rt/lib/gwp_asan/CMakeLists.txt @@ -25,8 +25,6 @@ set(GWP_ASAN_CFLAGS -fno-rtti -fno-exceptions -nostdinc++ -pthread) append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC GWP_ASAN_CFLAGS) append_list_if(COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG -fno-omit-frame-pointer GWP_ASAN_CFLAGS) -append_list_if(COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG - -mno-omit-leaf-frame-pointer GWP_ASAN_CFLAGS) # Remove -stdlib= which is unused when passing -nostdinc++. string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) diff --git a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h index 400d50c0b0b70b..28a41110faede8 100644 --- a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h +++ b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h @@ -132,6 +132,10 @@ class GuardedPoolAllocator { // occur. static void reportError(uintptr_t AccessPtr, Error E = Error::UNKNOWN); + // Get the current thread ID, or kInvalidThreadID if failure. Note: This + // implementation is platform-specific. + static uint64_t getThreadID(); + private: static constexpr size_t kInvalidSlotID = SIZE_MAX; @@ -146,10 +150,6 @@ class GuardedPoolAllocator { void markReadWrite(void *Ptr, size_t Size) const; void markInaccessible(void *Ptr, size_t Size) const; - // Get the current thread ID, or kInvalidThreadID if failure. Note: This - // implementation is platform-specific. - static uint64_t getThreadID(); - // Get the page size from the platform-specific implementation. Only needs to // be called once, and the result should be cached in PageSize in this class. static size_t getPlatformPageSize(); diff --git a/compiler-rt/lib/gwp_asan/random.cpp b/compiler-rt/lib/gwp_asan/random.cpp index 67f4a22ef95252..90493da7e03858 100644 --- a/compiler-rt/lib/gwp_asan/random.cpp +++ b/compiler-rt/lib/gwp_asan/random.cpp @@ -7,12 +7,14 @@ //===----------------------------------------------------------------------===// #include "gwp_asan/random.h" +#include "gwp_asan/guarded_pool_allocator.h" #include namespace gwp_asan { uint32_t getRandomUnsigned32() { - thread_local uint32_t RandomState = static_cast(time(nullptr)); + thread_local uint32_t RandomState = + time(nullptr) + GuardedPoolAllocator::getThreadID(); RandomState ^= RandomState << 13; RandomState ^= RandomState >> 17; RandomState ^= RandomState << 5; diff --git a/compiler-rt/lib/interception/interception_linux.cc b/compiler-rt/lib/interception/interception_linux.cc index d07f060b5b6421..4b27102a159c85 100644 --- a/compiler-rt/lib/interception/interception_linux.cc +++ b/compiler-rt/lib/interception/interception_linux.cc @@ -33,7 +33,7 @@ static int StrCmp(const char *s1, const char *s2) { } #endif -static void *GetFuncAddr(const char *name) { +static void *GetFuncAddr(const char *name, uptr wrapper_addr) { #if SANITIZER_NETBSD // FIXME: Find a better way to handle renames if (StrCmp(name, "sigaction")) @@ -47,13 +47,18 @@ static void *GetFuncAddr(const char *name) { // want the address of the real definition, though, so look it up using // RTLD_DEFAULT. addr = dlsym(RTLD_DEFAULT, name); + + // In case `name' is not loaded, dlsym ends up finding the actual wrapper. + // We don't want to intercept the wrapper and have it point to itself. + if ((uptr)addr == wrapper_addr) + addr = nullptr; } return addr; } bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func, uptr wrapper) { - void *addr = GetFuncAddr(name); + void *addr = GetFuncAddr(name, wrapper); *ptr_to_real = (uptr)addr; return addr && (func == wrapper); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 5b68c019190a06..9f5a91ac99dc6c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -1241,7 +1241,8 @@ INTERCEPTOR_WITH_SUFFIX(int, fputs, char *s, void *file) { // libc file streams can call user-supplied functions, see fopencookie. void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, fputs, s, file); - COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1); + if (!SANITIZER_MAC || s) + COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1); return REAL(fputs)(s, file); } #define INIT_FPUTS COMMON_INTERCEPT_FUNCTION(fputs) @@ -1254,7 +1255,8 @@ INTERCEPTOR(int, puts, char *s) { // libc file streams can call user-supplied functions, see fopencookie. void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, puts, s); - COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1); + if (!SANITIZER_MAC || s) + COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1); return REAL(puts)(s); } #define INIT_PUTS COMMON_INTERCEPT_FUNCTION(puts) diff --git a/compiler-rt/lib/scudo/CMakeLists.txt b/compiler-rt/lib/scudo/CMakeLists.txt index 9ee615c787de7b..2a560b8fcb7f04 100644 --- a/compiler-rt/lib/scudo/CMakeLists.txt +++ b/compiler-rt/lib/scudo/CMakeLists.txt @@ -14,10 +14,6 @@ append_list_if(COMPILER_RT_HAS_LIBPTHREAD pthread SCUDO_MINIMAL_DYNAMIC_LIBS) append_list_if(COMPILER_RT_HAS_LIBLOG log SCUDO_MINIMAL_DYNAMIC_LIBS) append_list_if(COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG -fno-omit-frame-pointer SCUDO_CFLAGS) -if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - append_list_if(COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG - -mno-omit-leaf-frame-pointer SCUDO_CFLAGS) -endif() set(SCUDO_DYNAMIC_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS}) # Use gc-sections by default to avoid unused code being pulled in. diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc index 5d9284c525084b..ec8606f65d5c26 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc @@ -67,11 +67,6 @@ extern "C" void *__libc_stack_end; void *__libc_stack_end = 0; #endif -#if SANITIZER_LINUX && defined(__aarch64__) -__tsan::uptr InitializeGuardPtr() __attribute__((visibility("hidden"))); -extern "C" __tsan::uptr _tsan_pointer_chk_guard; -#endif - #if SANITIZER_LINUX && defined(__aarch64__) && !SANITIZER_GO # define INIT_LONGJMP_XOR_KEY 1 #else @@ -302,26 +297,8 @@ void InitializePlatform() { CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1); reexec = true; } - // Initialize the guard pointer used in {sig}{set,long}jump. - longjmp_xor_key = InitializeGuardPtr(); - // uptr old_value = longjmp_xor_key; - // InitializeLongjmpXorKey(); - // CHECK_EQ(longjmp_xor_key, old_value); - // If the above check fails for you, please contact me (jlettner@apple.com) - // and let me know the values of the two differing keys. Please also set a - // breakpoint on `InitializeGuardPtr` and `InitializeLongjmpXorKey` and tell - // me the stack pointer (SP) values that go into the XOR operation (where we - // derive the key): - // - // InitializeLongjmpXorKey: - // uptr sp = (uptr)__builtin_frame_address(0); - // - // InitializeGuardPtr (in tsan_rtl_aarch64.S): - // mov x0, sp - // ... - // eor x0, x0, x1 - // - // Then feel free to comment out the call to `InitializeLongjmpXorKey`. + // Initialize the xor key used in {sig}{set,long}jump. + InitializeLongjmpXorKey(); #endif if (reexec) ReExec(); @@ -373,9 +350,7 @@ int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) { // Reverse operation of libc stack pointer mangling static uptr UnmangleLongJmpSp(uptr mangled_sp) { #if defined(__x86_64__) -# if SANITIZER_FREEBSD || SANITIZER_NETBSD - return mangled_sp; -# else // Linux +# if SANITIZER_LINUX // Reverse of: // xor %fs:0x30, %rsi // rol $0x11, %rsi @@ -385,6 +360,8 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) { : "=r" (sp) : "0" (mangled_sp)); return sp; +# else + return mangled_sp; # endif #elif defined(__aarch64__) # if SANITIZER_LINUX @@ -394,11 +371,11 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) { # endif #elif defined(__powerpc64__) // Reverse of: - // ld r4, -28696(r13) - // xor r4, r3, r4 - uptr xor_guard; - asm("ld %0, -28696(%%r13) \n" : "=r" (xor_guard)); - return mangled_sp ^ xor_guard; + // ld r4, -28696(r13) + // xor r4, r3, r4 + uptr xor_key; + asm("ld %0, -28696(%%r13)" : "=r" (xor_key)); + return mangled_sp ^ xor_key; #elif defined(__mips__) return mangled_sp; #else @@ -437,9 +414,10 @@ static void InitializeLongjmpXorKey() { jmp_buf env; REAL(_setjmp)(env); - // 2. Retrieve mangled/vanilla SP. + // 2. Retrieve vanilla/mangled SP. + uptr sp; + asm("mov %0, sp" : "=r" (sp)); uptr mangled_sp = ((uptr *)&env)[LONG_JMP_SP_ENV_SLOT]; - uptr sp = (uptr)__builtin_frame_address(0); // 3. xor SPs to obtain key. longjmp_xor_key = mangled_sp ^ sp; diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S b/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S index 55487bd7705383..e0b4c71dfed9a9 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_aarch64.S @@ -3,14 +3,6 @@ #include "sanitizer_common/sanitizer_asm.h" -#if !defined(__APPLE__) -.section .bss -.type __tsan_pointer_chk_guard, %object -ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__tsan_pointer_chk_guard)) -__tsan_pointer_chk_guard: -.zero 8 -#endif - #if defined(__APPLE__) .align 2 @@ -40,57 +32,6 @@ _sigsetjmp$non_lazy_ptr: .align 3 #endif -#if !defined(__APPLE__) -// GLIBC mangles the function pointers in jmp_buf (used in {set,long}*jmp -// functions) by XORing them with a random guard pointer. For AArch64 it is a -// global variable rather than a TCB one (as for x86_64/powerpc) and althought -// its value is exported by the loader, it lies within a private GLIBC -// namespace (meaning it should be only used by GLIBC itself and the ABI is -// not stable). So InitializeGuardPtr obtains the pointer guard value by -// issuing a setjmp and checking the resulting pointers values against the -// original ones. -ASM_HIDDEN(_Z18InitializeGuardPtrv) -.global _Z18InitializeGuardPtrv -ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(_Z18InitializeGuardPtrv)) -_Z18InitializeGuardPtrv: - CFI_STARTPROC - // Allocates a jmp_buf for the setjmp call. - stp x29, x30, [sp, -336]! - CFI_DEF_CFA_OFFSET (336) - CFI_OFFSET (29, -336) - CFI_OFFSET (30, -328) - add x29, sp, 0 - CFI_DEF_CFA_REGISTER (29) - add x0, x29, 24 - - // Call libc setjmp that mangle the stack pointer value - adrp x1, :got:_ZN14__interception12real__setjmpE - ldr x1, [x1, #:got_lo12:_ZN14__interception12real__setjmpE] - ldr x1, [x1] - blr x1 - - // glibc setjmp mangles both the frame pointer (FP, pc+4 on blr) and the - // stack pointer (SP). FP will be placed on ((uintptr*)jmp_buf)[11] and - // SP at ((uintptr*)jmp_buf)[13]. - // The mangle operation is just 'value' xor 'pointer guard value' and - // if we know the original value (SP) and the expected one, we can derive - // the guard pointer value. - mov x0, sp - - // Loads the mangled SP pointer. - ldr x1, [x29, 128] - eor x0, x0, x1 - adrp x2, __tsan_pointer_chk_guard - str x0, [x2, #:lo12:__tsan_pointer_chk_guard] - ldp x29, x30, [sp], 336 - CFI_RESTORE (30) - CFI_RESTORE (19) - CFI_DEF_CFA (31, 0) - ret - CFI_ENDPROC -ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(_Z18InitializeGuardPtrv)) -#endif - ASM_HIDDEN(__tsan_setjmp) .comm _ZN14__interception11real_setjmpE,8,8 .globl ASM_SYMBOL_INTERCEPTOR(setjmp) @@ -98,7 +39,7 @@ ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(setjmp)) ASM_SYMBOL_INTERCEPTOR(setjmp): CFI_STARTPROC - // save env parameters for function call + // Save frame/link register stp x29, x30, [sp, -32]! CFI_DEF_CFA_OFFSET (32) CFI_OFFSET (29, -32) @@ -108,10 +49,9 @@ ASM_SYMBOL_INTERCEPTOR(setjmp): add x29, sp, 0 CFI_DEF_CFA_REGISTER (29) - // Save jmp_buf - str x19, [sp, 16] - CFI_OFFSET (19, -16) - mov x19, x0 + // Save env parameter + str x0, [sp, 16] + CFI_OFFSET (0, -16) // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)` add x0, x29, 32 @@ -119,12 +59,14 @@ ASM_SYMBOL_INTERCEPTOR(setjmp): // call tsan interceptor bl ASM_SYMBOL(__tsan_setjmp) - // restore env parameter - mov x0, x19 - ldr x19, [sp, 16] + // Restore env parameter + ldr x0, [sp, 16] + CFI_RESTORE (0) + + // Restore frame/link register ldp x29, x30, [sp], 32 + CFI_RESTORE (29) CFI_RESTORE (30) - CFI_RESTORE (19) CFI_DEF_CFA (31, 0) // tail jump to libc setjmp @@ -148,7 +90,7 @@ ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(_setjmp)) ASM_SYMBOL_INTERCEPTOR(_setjmp): CFI_STARTPROC - // save env parameters for function call + // Save frame/link register stp x29, x30, [sp, -32]! CFI_DEF_CFA_OFFSET (32) CFI_OFFSET (29, -32) @@ -158,10 +100,9 @@ ASM_SYMBOL_INTERCEPTOR(_setjmp): add x29, sp, 0 CFI_DEF_CFA_REGISTER (29) - // Save jmp_buf - str x19, [sp, 16] - CFI_OFFSET (19, -16) - mov x19, x0 + // Save env parameter + str x0, [sp, 16] + CFI_OFFSET (0, -16) // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)` add x0, x29, 32 @@ -169,12 +110,14 @@ ASM_SYMBOL_INTERCEPTOR(_setjmp): // call tsan interceptor bl ASM_SYMBOL(__tsan_setjmp) - // Restore jmp_buf parameter - mov x0, x19 - ldr x19, [sp, 16] + // Restore env parameter + ldr x0, [sp, 16] + CFI_RESTORE (0) + + // Restore frame/link register ldp x29, x30, [sp], 32 + CFI_RESTORE (29) CFI_RESTORE (30) - CFI_RESTORE (19) CFI_DEF_CFA (31, 0) // tail jump to libc setjmp @@ -198,7 +141,7 @@ ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(sigsetjmp)) ASM_SYMBOL_INTERCEPTOR(sigsetjmp): CFI_STARTPROC - // save env parameters for function call + // Save frame/link register stp x29, x30, [sp, -32]! CFI_DEF_CFA_OFFSET (32) CFI_OFFSET (29, -32) @@ -208,12 +151,10 @@ ASM_SYMBOL_INTERCEPTOR(sigsetjmp): add x29, sp, 0 CFI_DEF_CFA_REGISTER (29) - // Save jmp_buf and savesigs - stp x19, x20, [sp, 16] - CFI_OFFSET (19, -16) - CFI_OFFSET (20, -8) - mov w20, w1 - mov x19, x0 + // Save env and savesigs parameter + stp x0, x1, [sp, 16] + CFI_OFFSET (0, -16) + CFI_OFFSET (1, -8) // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)` add x0, x29, 32 @@ -221,15 +162,15 @@ ASM_SYMBOL_INTERCEPTOR(sigsetjmp): // call tsan interceptor bl ASM_SYMBOL(__tsan_setjmp) - // restore env parameter - mov w1, w20 - mov x0, x19 - ldp x19, x20, [sp, 16] + // Restore env and savesigs parameter + ldp x0, x1, [sp, 16] + CFI_RESTORE (0) + CFI_RESTORE (1) + + // Restore frame/link register ldp x29, x30, [sp], 32 - CFI_RESTORE (30) CFI_RESTORE (29) - CFI_RESTORE (19) - CFI_RESTORE (20) + CFI_RESTORE (30) CFI_DEF_CFA (31, 0) // tail jump to libc sigsetjmp @@ -253,7 +194,7 @@ ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp)) ASM_SYMBOL_INTERCEPTOR(__sigsetjmp): CFI_STARTPROC - // save env parameters for function call + // Save frame/link register stp x29, x30, [sp, -32]! CFI_DEF_CFA_OFFSET (32) CFI_OFFSET (29, -32) @@ -263,12 +204,10 @@ ASM_SYMBOL_INTERCEPTOR(__sigsetjmp): add x29, sp, 0 CFI_DEF_CFA_REGISTER (29) - // Save jmp_buf and savesigs - stp x19, x20, [sp, 16] - CFI_OFFSET (19, -16) - CFI_OFFSET (20, -8) - mov w20, w1 - mov x19, x0 + // Save env and savesigs parameter + stp x0, x1, [sp, 16] + CFI_OFFSET (0, -16) + CFI_OFFSET (1, -8) // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)` add x0, x29, 32 @@ -276,14 +215,15 @@ ASM_SYMBOL_INTERCEPTOR(__sigsetjmp): // call tsan interceptor bl ASM_SYMBOL(__tsan_setjmp) - mov w1, w20 - mov x0, x19 - ldp x19, x20, [sp, 16] + // Restore env and savesigs parameter + ldp x0, x1, [sp, 16] + CFI_RESTORE (0) + CFI_RESTORE (1) + + // Restore frame/link register ldp x29, x30, [sp], 32 - CFI_RESTORE (30) CFI_RESTORE (29) - CFI_RESTORE (19) - CFI_RESTORE (20) + CFI_RESTORE (30) CFI_DEF_CFA (31, 0) // tail jump to libc __sigsetjmp diff --git a/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc index 839bba3691f91e..9c324cc19a11f5 100644 --- a/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc +++ b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.cc @@ -185,18 +185,17 @@ static bool handleFunctionTypeMismatch(FunctionTypeMismatchData *Data, return true; } -void __ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data, - ValueHandle Function, - ValueHandle calleeRTTI, - ValueHandle fnRTTI) { +void __ubsan_handle_function_type_mismatch_v1(FunctionTypeMismatchData *Data, + ValueHandle Function, + ValueHandle calleeRTTI, + ValueHandle fnRTTI) { GET_REPORT_OPTIONS(false); handleFunctionTypeMismatch(Data, Function, calleeRTTI, fnRTTI, Opts); } -void __ubsan_handle_function_type_mismatch_abort(FunctionTypeMismatchData *Data, - ValueHandle Function, - ValueHandle calleeRTTI, - ValueHandle fnRTTI) { +void __ubsan_handle_function_type_mismatch_v1_abort( + FunctionTypeMismatchData *Data, ValueHandle Function, + ValueHandle calleeRTTI, ValueHandle fnRTTI) { GET_REPORT_OPTIONS(true); if (handleFunctionTypeMismatch(Data, Function, calleeRTTI, fnRTTI, Opts)) Die(); diff --git a/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h index be2345dc166eb4..f7b9fc54f4724b 100644 --- a/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h +++ b/compiler-rt/lib/ubsan/ubsan_handlers_cxx.h @@ -40,14 +40,15 @@ struct FunctionTypeMismatchData { }; extern "C" SANITIZER_INTERFACE_ATTRIBUTE void -__ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data, - ValueHandle Val, ValueHandle calleeRTTI, - ValueHandle fnRTTI); +__ubsan_handle_function_type_mismatch_v1(FunctionTypeMismatchData *Data, + ValueHandle Val, + ValueHandle calleeRTTI, + ValueHandle fnRTTI); extern "C" SANITIZER_INTERFACE_ATTRIBUTE void -__ubsan_handle_function_type_mismatch_abort(FunctionTypeMismatchData *Data, - ValueHandle Val, - ValueHandle calleeRTTI, - ValueHandle fnRTTI); +__ubsan_handle_function_type_mismatch_v1_abort(FunctionTypeMismatchData *Data, + ValueHandle Val, + ValueHandle calleeRTTI, + ValueHandle fnRTTI); } #endif // UBSAN_HANDLERS_H diff --git a/compiler-rt/lib/ubsan/ubsan_interface.inc b/compiler-rt/lib/ubsan/ubsan_interface.inc index 3eb07b7b9fe35b..1e44bc2171ded1 100644 --- a/compiler-rt/lib/ubsan/ubsan_interface.inc +++ b/compiler-rt/lib/ubsan/ubsan_interface.inc @@ -21,8 +21,8 @@ INTERFACE_FUNCTION(__ubsan_handle_dynamic_type_cache_miss) INTERFACE_FUNCTION(__ubsan_handle_dynamic_type_cache_miss_abort) INTERFACE_FUNCTION(__ubsan_handle_float_cast_overflow) INTERFACE_FUNCTION(__ubsan_handle_float_cast_overflow_abort) -INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch) -INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_abort) +INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_v1) +INTERFACE_FUNCTION(__ubsan_handle_function_type_mismatch_v1_abort) INTERFACE_FUNCTION(__ubsan_handle_implicit_conversion) INTERFACE_FUNCTION(__ubsan_handle_implicit_conversion_abort) INTERFACE_FUNCTION(__ubsan_handle_invalid_builtin) diff --git a/compiler-rt/test/asan/TestCases/Linux/dlopen-mixed-c-cxx.c b/compiler-rt/test/asan/TestCases/Linux/dlopen-mixed-c-cxx.c new file mode 100644 index 00000000000000..8bce907ef2e6a7 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/Linux/dlopen-mixed-c-cxx.c @@ -0,0 +1,42 @@ +// RUN: %clangxx_asan -xc++ -shared -fPIC -o %t.so - < %s +// RUN: %clang_asan %s -o %t.out -ldl +// RUN: ASAN_OPTIONS=verbosity=1 not %t.out %t.so 2>&1 | FileCheck %s +// +// CHECK: AddressSanitizer: failed to intercept '__cxa_throw' +// +// dlopen() can not be intercepted on Android +// UNSUPPORTED: android +#ifdef __cplusplus + +static void foo(void) { + int i = 0; + throw(i); +} + +extern "C" { +int bar(void); +}; +int bar(void) { + try { + foo(); + } catch (int i) { + return i; + } + return -1; +} + +#else + +#include +#include + +int main(int argc, char **argv) { + int (*bar)(void); + void *handle = dlopen(argv[1], RTLD_LAZY); + assert(handle); + bar = dlsym(handle, "bar"); + assert(bar); + return bar(); +} + +#endif diff --git a/compiler-rt/test/fuzzer/fork.test b/compiler-rt/test/fuzzer/fork.test index bcc9b550e70ed5..e0f348b2bff1b4 100644 --- a/compiler-rt/test/fuzzer/fork.test +++ b/compiler-rt/test/fuzzer/fork.test @@ -1,4 +1,4 @@ -# UNSUPPORTED: darwin, freebsd +# UNSUPPORTED: darwin, freebsd, aarch64 BINGO: BINGO RUN: %cpp_compiler %S/SimpleTest.cpp -o %t-SimpleTest RUN: not %run %t-SimpleTest -fork=1 2>&1 | FileCheck %s --check-prefix=BINGO diff --git a/compiler-rt/test/hwasan/TestCases/cfi.cc b/compiler-rt/test/hwasan/TestCases/cfi.cc index 457e29659e77d9..e64b556171e627 100644 --- a/compiler-rt/test/hwasan/TestCases/cfi.cc +++ b/compiler-rt/test/hwasan/TestCases/cfi.cc @@ -1,4 +1,4 @@ -// RUN: %clang_hwasan -fsanitize=cfi -fno-sanitize-trap=cfi -flto -fvisibility=hidden -fuse-ld=lld %s -o %t +// RUN: %clangxx_hwasan -fsanitize=cfi -fno-sanitize-trap=cfi -flto -fvisibility=hidden -fuse-ld=lld %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s // REQUIRES: android diff --git a/compiler-rt/test/sanitizer_common/TestCases/Darwin/fputs_puts_null.cc b/compiler-rt/test/sanitizer_common/TestCases/Darwin/fputs_puts_null.cc new file mode 100644 index 00000000000000..705ca2e981cb21 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Darwin/fputs_puts_null.cc @@ -0,0 +1,16 @@ +// On Darwin, the man page states that "both fputs() and puts() print `(null)' +// if str is NULL." +// +// RUN: %clangxx -g %s -o %t && %run %t | FileCheck %s +// CHECK: {{^\(null\)---\(null\)$}} + +#include +#include + +int main(void) { + assert(fputs(NULL, stdout) >= 0); + fputs("---", stdout); + assert(puts(NULL) >= 0); + + return 0; +} diff --git a/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp b/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp index 31baa2af8ca9d2..07402fdcd70853 100644 --- a/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp +++ b/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp @@ -1,11 +1,53 @@ -// RUN: %clangxx -std=c++17 -fsanitize=function %s -O3 -g -o %t -// RUN: %run %t 2>&1 | FileCheck %s +// RUN: %clangxx -DDETERMINE_UNIQUE %s -o %t-unique +// RUN: %clangxx -std=c++17 -fsanitize=function %s -O3 -g -DSHARED_LIB -fPIC -shared -o %t-so.so +// RUN: %clangxx -std=c++17 -fsanitize=function %s -O3 -g -o %t %t-so.so +// RUN: %run %t 2>&1 | FileCheck %s --check-prefix=CHECK $(%run %t-unique UNIQUE) // Verify that we can disable symbolization if needed: -// RUN: %env_ubsan_opts=symbolize=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOSYM +// RUN: %env_ubsan_opts=symbolize=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOSYM $(%run %t-unique NOSYM-UNIQUE) // XFAIL: windows-msvc // Unsupported function flag // UNSUPPORTED: openbsd +#ifdef DETERMINE_UNIQUE + +#include + +#include "../../../../../lib/sanitizer_common/sanitizer_platform.h" + +int main(int, char **argv) { + if (!SANITIZER_NON_UNIQUE_TYPEINFO) + std::cout << "--check-prefix=" << argv[1]; +} + +#else + +struct Shared {}; +using FnShared = void (*)(Shared *); +FnShared getShared(); + +struct __attribute__((visibility("hidden"))) Hidden {}; +using FnHidden = void (*)(Hidden *); +FnHidden getHidden(); + +namespace { +struct Private {}; +} // namespace +using FnPrivate = void (*)(void *); +FnPrivate getPrivate(); + +#ifdef SHARED_LIB + +void fnShared(Shared *) {} +FnShared getShared() { return fnShared; } + +void fnHidden(Hidden *) {} +FnHidden getHidden() { return fnHidden; } + +void fnPrivate(Private *) {} +FnPrivate getPrivate() { return reinterpret_cast(fnPrivate); } + +#else + #include void f() {} @@ -64,12 +106,31 @@ void check_noexcept_calls() { p2(0); } +void check_cross_dso() { + getShared()(nullptr); + + // UNIQUE: function.cpp:[[@LINE+2]]:3: runtime error: call to function fnHidden(Hidden*) through pointer to incorrect function type 'void (*)(Hidden *)' + // NOSYM-UNIQUE: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(Hidden *)' + getHidden()(nullptr); + + // TODO: Unlike GCC, Clang fails to prefix the typeinfo name for the function + // type with "*", so this erroneously only fails for "*UNIQUE": + // UNIQUE: function.cpp:[[@LINE+2]]:3: runtime error: call to function fnPrivate((anonymous namespace)::Private*) through pointer to incorrect function type 'void (*)((anonymous namespace)::Private *)' + // NOSYM-UNIQUE: function.cpp:[[@LINE+1]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)((anonymous namespace)::Private *)' + reinterpret_cast(getPrivate())(nullptr); +} + int main(void) { make_valid_call(); make_invalid_call(); check_noexcept_calls(); + check_cross_dso(); // Check that no more errors will be printed. // CHECK-NOT: runtime error: call to function // NOSYM-NOT: runtime error: call to function make_invalid_call(); } + +#endif + +#endif diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt index fd74c2742e0a9e..ddcd478b2139d2 100644 --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -27,7 +27,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBCXX_STANDALONE_BUIL project(libcxx CXX C) set(PACKAGE_NAME libcxx) - set(PACKAGE_VERSION 9.0.0svn) + set(PACKAGE_VERSION 9.0.0) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") @@ -151,8 +151,10 @@ set_property(CACHE LIBCXX_CXX_ABI PROPERTY STRINGS ;${CXXABIS}) # Without this all the bots fail while building libc++ if (DEFINED ENV{USER}) if (("$ENV{USER}" STREQUAL "buildbot") OR (("$ENV{USER}" STREQUAL "llvmbb") OR ("$ENV{USER}" STREQUAL "buildslave"))) - message(WARNING "OVERRIDING BUILDBOT CONFIG") - set(LIBCXX_CXX_ABI "default" CACHE STRING "FIXME" FORCE) + if (LIBCXX_CXX_ABI STREQUAL "libcxxabi" AND NOT DEFINED LIBCXX_CXX_ABI_INCLUDE_PATHS) + message(WARNING "OVERRIDING BUILDBOT CONFIG") + set(LIBCXX_CXX_ABI "default" CACHE STRING "FIXME" FORCE) + endif() endif() endif() # Setup the default options if LIBCXX_CXX_ABI is not specified. diff --git a/libcxx/include/map b/libcxx/include/map index 6805a513394a3f..eb6ae57b011f89 100644 --- a/libcxx/include/map +++ b/libcxx/include/map @@ -193,8 +193,8 @@ public: const_iterator find(const K& x) const; // C++14 template size_type count(const K& x) const; // C++14 - size_type count(const key_type& k) const; + bool contains(const key_type& x) const; // C++20 iterator lower_bound(const key_type& k); const_iterator lower_bound(const key_type& k) const; template @@ -407,8 +407,8 @@ public: const_iterator find(const K& x) const; // C++14 template size_type count(const K& x) const; // C++14 - size_type count(const key_type& k) const; + bool contains(const key_type& x) const; // C++20 iterator lower_bound(const key_type& k); const_iterator lower_bound(const key_type& k) const; template @@ -1398,6 +1398,12 @@ public: typename enable_if<__is_transparent<_Compare, _K2>::value,size_type>::type count(const _K2& __k) const {return __tree_.__count_multi(__k);} #endif + +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const key_type& __k) {return __tree_.lower_bound(__k);} @@ -2055,6 +2061,12 @@ public: typename enable_if<__is_transparent<_Compare, _K2>::value,size_type>::type count(const _K2& __k) const {return __tree_.__count_multi(__k);} #endif + +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const key_type& __k) {return __tree_.lower_bound(__k);} diff --git a/libcxx/include/set b/libcxx/include/set index 79e8f29f0b9437..70ab4d37add208 100644 --- a/libcxx/include/set +++ b/libcxx/include/set @@ -155,9 +155,9 @@ public: template const_iterator find(const K& x) const; // C++14 template - size_type count(const K& x) const; // C++14 - + size_type count(const K& x) const; // C++14 size_type count(const key_type& k) const; + bool contains(const key_type& x) const; // C++20 iterator lower_bound(const key_type& k); const_iterator lower_bound(const key_type& k) const; template @@ -354,8 +354,10 @@ public: iterator find(const K& x); template const_iterator find(const K& x) const; // C++14 - + template + size_type count(const K& x) const; // C++14 size_type count(const key_type& k) const; + bool contains(const key_type& x) const; // C++20 iterator lower_bound(const key_type& k); const_iterator lower_bound(const key_type& k) const; template @@ -787,6 +789,12 @@ public: typename enable_if<__is_transparent<_Compare, _K2>::value,size_type>::type count(const _K2& __k) const {return __tree_.__count_multi(__k);} #endif + +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const key_type& __k) {return __tree_.lower_bound(__k);} @@ -1307,6 +1315,11 @@ public: count(const _K2& __k) const {return __tree_.__count_multi(__k);} #endif +#if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY iterator lower_bound(const key_type& __k) {return __tree_.lower_bound(__k);} diff --git a/libcxx/include/tuple b/libcxx/include/tuple index de30e86c72b483..031d25a9854fce 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -601,6 +601,25 @@ class _LIBCPP_TEMPLATE_VIS tuple } }; + template + using _EnableImplicitTupleLikeConstructor = _EnableIf< + _CheckTupleLikeConstructor< + __tuple_like_with_size<_Tuple, sizeof...(_Tp)>::value + && !_PackExpandsToThisTuple<_Tuple>::value + && (!is_lvalue_reference<_Tuple>::value || !_DisableIfLValue) + >::template __enable_implicit<_Tuple>(), + bool + >; + + template + using _EnableExplicitTupleLikeConstructor = _EnableIf< + _CheckTupleLikeConstructor< + __tuple_like_with_size<_Tuple, sizeof...(_Tp)>::value + && !_PackExpandsToThisTuple<_Tuple>::value + && (!is_lvalue_reference<_Tuple>::value || !_DisableIfLValue) + >::template __enable_explicit<_Tuple>(), + bool + >; template friend _LIBCPP_CONSTEXPR_AFTER_CXX11 typename tuple_element<_Jp, tuple<_Up...> >::type& get(tuple<_Up...>&) _NOEXCEPT; template friend _LIBCPP_CONSTEXPR_AFTER_CXX11 @@ -815,35 +834,27 @@ public: typename __make_tuple_types::type(), _VSTD::forward<_Up>(__u)...) {} - template ::value - && !_PackExpandsToThisTuple<_Tuple>::value - >::template __enable_implicit<_Tuple>(), - bool - >::type = false - > + template = false> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 tuple(_Tuple&& __t) _NOEXCEPT_((is_nothrow_constructible<_BaseT, _Tuple>::value)) : __base_(_VSTD::forward<_Tuple>(__t)) {} - template ::value - && !_PackExpandsToThisTuple<_Tuple>::value - >::template __enable_explicit<_Tuple>(), - bool - >::type = false - > + template = false> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 + tuple(const _Tuple& __t) _NOEXCEPT_((is_nothrow_constructible<_BaseT, const _Tuple&>::value)) + : __base_(__t) {} + template = false> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 explicit tuple(_Tuple&& __t) _NOEXCEPT_((is_nothrow_constructible<_BaseT, _Tuple>::value)) : __base_(_VSTD::forward<_Tuple>(__t)) {} + template = false> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 + explicit + tuple(const _Tuple& __t) _NOEXCEPT_((is_nothrow_constructible<_BaseT, const _Tuple&>::value)) + : __base_(__t) {} + template equal_range(const key_type& k); pair equal_range(const key_type& k) const; @@ -355,6 +356,7 @@ public: iterator find(const key_type& k); const_iterator find(const key_type& k) const; size_type count(const key_type& k) const; + bool contains(const key_type& k) const; // C++20 pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; @@ -844,9 +846,9 @@ public: // types typedef _Key key_type; typedef _Tp mapped_type; - typedef _Hash hasher; - typedef _Pred key_equal; - typedef _Alloc allocator_type; + typedef typename __identity<_Hash>::type hasher; + typedef typename __identity<_Pred>::type key_equal; + typedef typename __identity<_Alloc>::type allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; @@ -1278,6 +1280,10 @@ public: const_iterator find(const key_type& __k) const {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_unique(__k);} + #if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} + #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __table_.__equal_range_unique(__k);} @@ -1348,6 +1354,73 @@ private: #endif }; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template>, + class _Pred = equal_to<__iter_key_type<_InputIterator>>, + class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>, + class = _EnableIf::value>, + class = _EnableIf::value>, + class = _EnableIf::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_map(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type = 0, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Hash, _Pred, _Allocator>; + +template>, + class _Pred = equal_to>, + class _Allocator = allocator>, + class = _EnableIf::value>, + class = _EnableIf::value>, + class = _EnableIf::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_map(initializer_list>, typename allocator_traits<_Allocator>::size_type = 0, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_map, _Tp, _Hash, _Pred, _Allocator>; + +template::value>> +unordered_map(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, + hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; + +template::value>> +unordered_map(_InputIterator, _InputIterator, _Allocator) + -> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, + hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; + +template::value>, + class = _EnableIf::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_map(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) + -> unordered_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, + _Hash, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; + +template::value>> +unordered_map(initializer_list>, typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_map, _Tp, + hash>, + equal_to>, _Allocator>; + +template::value>> +unordered_map(initializer_list>, _Allocator) + -> unordered_map, _Tp, + hash>, + equal_to>, _Allocator>; + +template::value>, + class = _EnableIf::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_map(initializer_list>, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) + -> unordered_map, _Tp, _Hash, + equal_to>, _Allocator>; +#endif + template unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map( size_type __n, const hasher& __hf, const key_equal& __eql) @@ -1673,9 +1746,9 @@ public: // types typedef _Key key_type; typedef _Tp mapped_type; - typedef _Hash hasher; - typedef _Pred key_equal; - typedef _Alloc allocator_type; + typedef typename __identity<_Hash>::type hasher; + typedef typename __identity<_Pred>::type key_equal; + typedef typename __identity<_Alloc>::type allocator_type; typedef pair value_type; typedef value_type& reference; typedef const value_type& const_reference; @@ -1982,6 +2055,10 @@ public: const_iterator find(const key_type& __k) const {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_multi(__k);} + #if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} + #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __table_.__equal_range_multi(__k);} @@ -2041,6 +2118,73 @@ public: }; +#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES +template>, + class _Pred = equal_to<__iter_key_type<_InputIterator>>, + class _Allocator = allocator<__iter_to_alloc_type<_InputIterator>>, + class = _EnableIf::value>, + class = _EnableIf::value>, + class = _EnableIf::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_multimap(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type = 0, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Hash, _Pred, _Allocator>; + +template>, + class _Pred = equal_to>, + class _Allocator = allocator>, + class = _EnableIf::value>, + class = _EnableIf::value>, + class = _EnableIf::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_multimap(initializer_list>, typename allocator_traits<_Allocator>::size_type = 0, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_multimap, _Tp, _Hash, _Pred, _Allocator>; + +template::value>> +unordered_multimap(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, + hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; + +template::value>> +unordered_multimap(_InputIterator, _InputIterator, _Allocator) + -> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, + hash<__iter_key_type<_InputIterator>>, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; + +template::value>, + class = _EnableIf::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_multimap(_InputIterator, _InputIterator, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) + -> unordered_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, + _Hash, equal_to<__iter_key_type<_InputIterator>>, _Allocator>; + +template::value>> +unordered_multimap(initializer_list>, typename allocator_traits<_Allocator>::size_type, _Allocator) + -> unordered_multimap, _Tp, + hash>, + equal_to>, _Allocator>; + +template::value>> +unordered_multimap(initializer_list>, _Allocator) + -> unordered_multimap, _Tp, + hash>, + equal_to>, _Allocator>; + +template::value>, + class = _EnableIf::value>, + class = _EnableIf<__is_allocator<_Allocator>::value>> +unordered_multimap(initializer_list>, typename allocator_traits<_Allocator>::size_type, _Hash, _Allocator) + -> unordered_multimap, _Tp, _Hash, + equal_to>, _Allocator>; +#endif + template unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_multimap( size_type __n, const hasher& __hf, const key_equal& __eql) diff --git a/libcxx/include/unordered_set b/libcxx/include/unordered_set index 4a9f0309327983..68f777a4ea3eb2 100644 --- a/libcxx/include/unordered_set +++ b/libcxx/include/unordered_set @@ -146,6 +146,7 @@ public: iterator find(const key_type& k); const_iterator find(const key_type& k) const; size_type count(const key_type& k) const; + bool contains(const key_type& k) const; // C++20 pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; @@ -310,6 +311,7 @@ public: iterator find(const key_type& k); const_iterator find(const key_type& k) const; size_type count(const key_type& k) const; + bool contains(const key_type& k) const; // C++20 pair equal_range(const key_type& k); pair equal_range(const key_type& k) const; @@ -677,6 +679,10 @@ public: const_iterator find(const key_type& __k) const {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_unique(__k);} + #if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} + #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __table_.__equal_range_unique(__k);} @@ -1304,6 +1310,10 @@ public: const_iterator find(const key_type& __k) const {return __table_.find(__k);} _LIBCPP_INLINE_VISIBILITY size_type count(const key_type& __k) const {return __table_.__count_multi(__k);} + #if _LIBCPP_STD_VER > 17 + _LIBCPP_INLINE_VISIBILITY + bool contains(const key_type& __k) const {return find(__k) != end();} + #endif // _LIBCPP_STD_VER > 17 _LIBCPP_INLINE_VISIBILITY pair equal_range(const key_type& __k) {return __table_.__equal_range_multi(__k);} diff --git a/libcxx/include/variant b/libcxx/include/variant index 420e8c2611f673..98a62c992fa12c 100644 --- a/libcxx/include/variant +++ b/libcxx/include/variant @@ -1089,52 +1089,73 @@ private: } }; -template -struct __overload; - -template <> -struct __overload<> { void operator()() const; }; +struct __no_narrowing_check { + template + using _Apply = __identity<_Dest>; +}; -template -struct __overload<_Tp, _Types...> : __overload<_Types...> { - using __overload<_Types...>::operator(); +struct __narrowing_check { + template + static auto __test_impl(_Dest (&&)[1]) -> __identity<_Dest>; + template + using _Apply _LIBCPP_NODEBUG_TYPE = decltype(__test_impl<_Dest>({std::declval<_Source>()})); +}; - static auto __test(_Tp (&&)[1]) -> __identity<_Tp>; +template +using __check_for_narrowing _LIBCPP_NODEBUG_TYPE = + typename _If< +#ifdef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT + false && +#endif + is_arithmetic<_Dest>::value, + __narrowing_check, + __no_narrowing_check + >::template _Apply<_Dest, _Source>; +template +struct __overload { template - auto operator()(_Tp, _Up&& __t) const -#ifndef _LIBCPP_ENABLE_NARROWING_CONVERSIONS_IN_VARIANT - -> decltype(__test({ _VSTD::forward<_Up>(__t) })); -#else - -> __identity<_Tp>; -#endif + auto operator()(_Tp, _Up&&) const -> __check_for_narrowing<_Tp, _Up>; }; -template -struct __overload_bool : _Base { - using _Base::operator(); - +template +struct __overload_bool { template > auto operator()(bool, _Up&&) const -> enable_if_t, __identity<_Tp>>; }; -template -struct __overload - : __overload_bool<__overload<_Types...>, bool> {}; -template -struct __overload - : __overload_bool<__overload<_Types...>, bool const> {}; -template -struct __overload - : __overload_bool<__overload<_Types...>, bool volatile> {}; -template -struct __overload - : __overload_bool<__overload<_Types...>, bool const volatile> {}; +template +struct __overload : __overload_bool {}; +template +struct __overload : __overload_bool {}; +template +struct __overload : __overload_bool {}; +template +struct __overload : __overload_bool {}; + +template +struct __all_overloads : _Bases... { + void operator()() const; + using _Bases::operator()...; +}; + +template +struct __make_overloads_imp; + +template +struct __make_overloads_imp<__tuple_indices<_Idx...> > { + template + using _Apply _LIBCPP_NODEBUG_TYPE = __all_overloads<__overload<_Types, _Idx>...>; +}; + +template +using _MakeOverloads _LIBCPP_NODEBUG_TYPE = typename __make_overloads_imp< + __make_indices_imp >::template _Apply<_Types...>; template using __best_match_t = - typename invoke_result_t<__overload<_Types...>, _Tp, _Tp>::type; + typename invoke_result_t<_MakeOverloads<_Types...>, _Tp, _Tp>::type; } // __variant_detail diff --git a/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp b/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp index 00e70d6025e51c..af214eaab1bf70 100644 --- a/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp +++ b/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp @@ -30,6 +30,10 @@ // XFAIL: availability=macosx10.8 // XFAIL: availability=macosx10.7 +// AppleClang < 10 incorrectly warns that aligned allocation is not supported +// even when it is supported. +// XFAIL: apple-clang-9 + // XFAIL: sanitizer-new-delete, ubsan // GCC doesn't support the aligned-allocation flags. diff --git a/libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_variant_overloads_impl.sh.cpp b/libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_variant_overloads_impl.sh.cpp new file mode 100644 index 00000000000000..013d434f40d7b2 --- /dev/null +++ b/libcxx/test/libcxx/utilities/meta/stress_tests/stress_test_variant_overloads_impl.sh.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This is a dummy feature that prevents this test from running by default. +// REQUIRES: template-cost-testing + +// Test the cost of the mechanism used to create an overload set used by variant +// to determine which alternative to construct. + +// The table below compares the compile time and object size for each of the +// variants listed in the RUN script. +// +// Impl Compile Time Object Size +// ----------------------------------------------------- +// flat: 959 ms 792 KiB +// recursive: 23,444 ms 23,000 KiB +// ----------------------------------------------------- +// variant_old: 16,894 ms 17,000 KiB +// variant_new: 1,105 ms 828 KiB + + +// RUN: %cxx %flags %compile_flags -std=c++17 -c %s \ +// RUN: -ggdb -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -g \ +// RUN: -DTEST_NS=flat_impl -o %S/flat.o +// RUN: %cxx %flags %compile_flags -std=c++17 -c %s \ +// RUN: -ggdb -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -g \ +// RUN: -DTEST_NS=rec_impl -o %S/rec.o +// RUN: %cxx %flags %compile_flags -std=c++17 -c %s \ +// RUN: -ggdb -ggnu-pubnames -ftemplate-depth=5000 -ftime-trace -g \ +// RUN: -DTEST_NS=variant_impl -o %S/variant.o + +#include +#include +#include +#include + +#include "test_macros.h" +#include "template_cost_testing.h" + +template +struct TestType {}; + +template +struct ID { + using type = T; +}; + +namespace flat_impl { + +struct OverloadBase { void operator()() const; }; + +template +struct Overload { + auto operator()(Tp, Tp) const -> ID; +}; + +template +struct AllOverloads : OverloadBase, Bases... {}; + +template +struct MakeOverloads; + +template +struct MakeOverloads > { + template + using Apply = AllOverloads...>; +}; + +template +using Overloads = typename MakeOverloads< + std::__make_indices_imp >::template Apply; + +} // namespace flat_impl + + +namespace rec_impl { + +template struct Overload; + +template <> +struct Overload<> { void operator()() const; }; + +template +struct Overload : Overload { + using Overload::operator(); + auto operator()(Tp, Tp) const -> ID; +}; + +template +using Overloads = Overload; + +} // namespace rec_impl + +namespace variant_impl { + template + using Overloads = std::__variant_detail::_MakeOverloads; +} // naamespace variant_impl + +#ifndef TEST_NS +#error TEST_NS must be defined +#endif + +#define TEST_TYPE() TestType< __COUNTER__ >, +using T1 = TEST_NS::Overloads, TestType<1>, int>; +static_assert(__COUNTER__ >= 1000, ""); + +void fn1(T1 x) { DoNotOptimize(&x); } +void fn2(typename std::invoke_result_t::type x) { DoNotOptimize(&x); } + +int main() { + DoNotOptimize(&fn1); + DoNotOptimize(&fn2); +} diff --git a/libcxx/test/std/containers/associative/map/contains.pass.cpp b/libcxx/test/std/containers/associative/map/contains.pass.cpp new file mode 100644 index 00000000000000..5b71eedba4d822 --- /dev/null +++ b/libcxx/test/std/containers/associative/map/contains.pass.cpp @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +#include +#include + +// + +// bool contains(const key_type& x) const; + +template +void test(B bad, Pairs... args) { + T map; + P pairs[] = {args...}; + + for (auto& p : pairs) map.insert(p); + for (auto& p : pairs) assert(map.contains(p.first)); + + assert(!map.contains(bad)); +} + +struct E { int a = 1; double b = 1; char c = 1; }; + +int main(int, char**) +{ + { + test, std::pair >( + 'e', std::make_pair('a', 10), std::make_pair('b', 11), + std::make_pair('c', 12), std::make_pair('d', 13)); + + test, std::pair >( + 'e', std::make_pair('a', 'a'), std::make_pair('b', 'a'), + std::make_pair('c', 'a'), std::make_pair('d', 'b')); + + test, std::pair >( + -1, std::make_pair(1, E{}), std::make_pair(2, E{}), + std::make_pair(3, E{}), std::make_pair(4, E{})); + } + { + test, std::pair >( + 'e', std::make_pair('a', 10), std::make_pair('b', 11), + std::make_pair('c', 12), std::make_pair('d', 13)); + + test, std::pair >( + 'e', std::make_pair('a', 'a'), std::make_pair('b', 'a'), + std::make_pair('c', 'a'), std::make_pair('d', 'b')); + + test, std::pair >( + -1, std::make_pair(1, E{}), std::make_pair(2, E{}), + std::make_pair(3, E{}), std::make_pair(4, E{})); + } + + return 0; +} + diff --git a/libcxx/test/std/containers/associative/set/contains.pass.cpp b/libcxx/test/std/containers/associative/set/contains.pass.cpp new file mode 100644 index 00000000000000..2b09729048723e --- /dev/null +++ b/libcxx/test/std/containers/associative/set/contains.pass.cpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +#include +#include + +// + +// bool contains(const key_type& x) const; + +template +void test(B bad, Vals... args) { + T set; + V vals[] = {args...}; + + for (auto& v : vals) set.insert(v); + for (auto& v : vals) assert(set.contains(v)); + + assert(!set.contains(bad)); +} + +struct E { int a = 1; double b = 1; char c = 1; }; + +int main(int, char**) +{ + { + test, int>(14, 10, 11, 12, 13); + test, char>('e', 'a', 'b', 'c', 'd'); + } + { + test, int>(14, 10, 11, 12, 13); + test, char>('e', 'a', 'b', 'c', 'd'); + } + + return 0; +} + diff --git a/libcxx/test/std/containers/unord/unord.map/contains.pass.cpp b/libcxx/test/std/containers/unord/unord.map/contains.pass.cpp new file mode 100644 index 00000000000000..c591e197249f44 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.map/contains.pass.cpp @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +#include +#include + +// + +// bool contains(const key_type& x) const; + +template +void test(B bad, Pairs... args) { + T map; + P pairs[] = {args...}; + + for (auto& p : pairs) map.insert(p); + for (auto& p : pairs) assert(map.contains(p.first)); + + assert(!map.contains(bad)); +} + +struct E { int a = 1; double b = 1; char c = 1; }; + +int main(int, char**) +{ + { + test, std::pair >( + 'e', std::make_pair('a', 10), std::make_pair('b', 11), + std::make_pair('c', 12), std::make_pair('d', 13)); + + test, std::pair >( + 'e', std::make_pair('a', 'a'), std::make_pair('b', 'a'), + std::make_pair('c', 'a'), std::make_pair('d', 'b')); + + test, std::pair >( + -1, std::make_pair(1, E{}), std::make_pair(2, E{}), + std::make_pair(3, E{}), std::make_pair(4, E{})); + } + { + test, std::pair >( + 'e', std::make_pair('a', 10), std::make_pair('b', 11), + std::make_pair('c', 12), std::make_pair('d', 13)); + + test, std::pair >( + 'e', std::make_pair('a', 'a'), std::make_pair('b', 'a'), + std::make_pair('c', 'a'), std::make_pair('d', 'b')); + + test, std::pair >( + -1, std::make_pair(1, E{}), std::make_pair(2, E{}), + std::make_pair(3, E{}), std::make_pair(4, E{})); + } + + return 0; +} + diff --git a/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.fail.cpp b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.fail.cpp new file mode 100644 index 00000000000000..642abce8a27bb4 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.fail.cpp @@ -0,0 +1,106 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides +// XFAIL: clang-6, apple-clang-9.0, apple-clang-9.1, apple-clang-10.0 + +// template>, +// class Pred = equal_to>, +// class Allocator = allocator>> +// unordered_map(InputIterator, InputIterator, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_map, iter-mapped-type, Hash, Pred, +// Allocator>; +// +// template, +// class Pred = equal_to, class Allocator = allocator>> +// unordered_map(initializer_list>, +// typename see below::size_type = see below, Hash = Hash(), +// Pred = Pred(), Allocator = Allocator()) +// -> unordered_map; +// +// template +// unordered_map(InputIterator, InputIterator, typename see below::size_type, Allocator) +// -> unordered_map, iter-mapped-type, +// hash>, +// equal_to>, Allocator>; +// +// template +// unordered_map(InputIterator, InputIterator, Allocator) +// -> unordered_map, iter-mapped-type, +// hash>, +// equal_to>, Allocator>; +// +// template +// unordered_map(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator) +// -> unordered_map, iter-mapped-type, Hash, +// equal_to>, Allocator>; +// +// template +// unordered_map(initializer_list>, typename see below::size_type, Allocator) +// -> unordered_map, equal_to, Allocator>; +// +// template +// unordered_map(initializer_list>, Allocator) +// -> unordered_map, equal_to, Allocator>; +// +// template +// unordered_map(initializer_list>, typename see below::size_type, Hash, +// Allocator) +// -> unordered_map, Allocator>; + +#include +#include + +int main(int, char**) +{ + using P = std::pair; + { + // cannot deduce Key from nothing + std::unordered_map m; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_map'}} + } + { + // cannot deduce Key from just (Size) + std::unordered_map m(42); // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_map'}} + } + { + // cannot deduce Key from just (Size, Hash) + std::unordered_map m(42, std::hash()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_map'}} + } + { + // cannot deduce Key from just (Size, Hash, Pred) + std::unordered_map m(42, std::hash(), std::equal_to()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_map'}} + } + { + // cannot deduce Key from just (Size, Hash, Pred, Allocator) + std::unordered_map m(42, std::hash(), std::equal_to(), std::allocator

    ()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_map'}} + } + { + // cannot deduce Key from just (Allocator) + std::unordered_map m(std::allocator

    {}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_map'}} + } + { + // cannot deduce Key from just (Size, Allocator) + std::unordered_map m(42, std::allocator

    ()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_map'}} + } + { + // cannot deduce Key from just (Size, Hash, Allocator) + std::unordered_map m(42, std::hash(), std::allocator

    ()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_map'}} + } + + return 0; +} diff --git a/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp new file mode 100644 index 00000000000000..0923597dcc9941 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp @@ -0,0 +1,204 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template>, +// class Pred = equal_to>, +// class Allocator = allocator>> +// unordered_map(InputIterator, InputIterator, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_map, iter-mapped-type, Hash, Pred, +// Allocator>; +// +// template, +// class Pred = equal_to, class Allocator = allocator>> +// unordered_map(initializer_list>, +// typename see below::size_type = see below, Hash = Hash(), +// Pred = Pred(), Allocator = Allocator()) +// -> unordered_map; +// +// template +// unordered_map(InputIterator, InputIterator, typename see below::size_type, Allocator) +// -> unordered_map, iter-mapped-type, +// hash>, +// equal_to>, Allocator>; +// +// template +// unordered_map(InputIterator, InputIterator, Allocator) +// -> unordered_map, iter-mapped-type, +// hash>, +// equal_to>, Allocator>; +// +// template +// unordered_map(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator) +// -> unordered_map, iter-mapped-type, Hash, +// equal_to>, Allocator>; +// +// template +// unordered_map(initializer_list>, typename see below::size_type, Allocator) +// -> unordered_map, equal_to, Allocator>; +// +// template +// unordered_map(initializer_list>, Allocator) +// -> unordered_map, equal_to, Allocator>; +// +// template +// unordered_map(initializer_list>, typename see below::size_type, Hash, +// Allocator) +// -> unordered_map, Allocator>; + +#include // is_permutation +#include +#include // INT_MAX +#include +#include + +#include "test_allocator.h" + +using P = std::pair; +using PC = std::pair; + +int main(int, char**) +{ + const PC expected_m[] = { {1,1}, {2,2}, {3,1}, {INT_MAX,1} }; + + { + const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_map m(std::begin(arr), std::end(arr)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_map m(std::begin(arr), std::end(arr), 42); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_map m(std::begin(arr), std::end(arr), 42, std::hash()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_map m(std::begin(arr), std::end(arr), 42, std::hash(), std::equal_to<>()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to<>>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_map m(std::begin(arr), std::end(arr), 42, std::hash(), std::equal_to<>(), test_allocator(0, 41)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to<>, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 41); + } + + { + std::unordered_map source; + std::unordered_map m(source); + ASSERT_SAME_TYPE(decltype(m), decltype(source)); + assert(m.size() == 0); + } + + { + std::unordered_map source; + std::unordered_map m{source}; // braces instead of parens + ASSERT_SAME_TYPE(decltype(m), decltype(source)); + assert(m.size() == 0); + } + + { + std::unordered_map, std::equal_to<>, test_allocator> source; + test_allocator a(0, 42); + std::unordered_map m(source, a); + ASSERT_SAME_TYPE(decltype(m), decltype(source)); + assert(m.get_allocator().get_id() == 42); + assert(m.size() == 0); + } + + { + std::unordered_map, std::equal_to<>, test_allocator> source; + test_allocator a(0, 43); + std::unordered_map m{source, a}; // braces instead of parens + ASSERT_SAME_TYPE(decltype(m), decltype(source)); + assert(m.get_allocator().get_id() == 43); + assert(m.size() == 0); + } + + { + std::unordered_map m { P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }; + ASSERT_SAME_TYPE(decltype(m), std::unordered_map); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_map m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_map m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42, std::hash()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_map m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42, std::hash(), std::equal_to<>()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to<>>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_map m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42, std::hash(), std::equal_to<>(), test_allocator(0, 44)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to<>, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 44); + } + + { + const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_map m(std::begin(arr), std::end(arr), 42, test_allocator(0, 45)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 45); + } + + { + const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_map m(std::begin(arr), std::end(arr), 42, std::hash(), test_allocator(0, 46)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 46); + } + + { + std::unordered_map m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42, test_allocator(0, 47)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 47); + } + + { + std::unordered_map m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42, std::hash(), test_allocator(0, 48)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 48); + } + + return 0; +} diff --git a/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct_const.pass.cpp b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct_const.pass.cpp new file mode 100644 index 00000000000000..1fb4d674d5fb00 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct_const.pass.cpp @@ -0,0 +1,172 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template>, +// class Pred = equal_to>, +// class Allocator = allocator>> +// unordered_map(InputIterator, InputIterator, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_map, iter-mapped-type, Hash, Pred, +// Allocator>; +// +// template, +// class Pred = equal_to, class Allocator = allocator>> +// unordered_map(initializer_list>, +// typename see below::size_type = see below, Hash = Hash(), +// Pred = Pred(), Allocator = Allocator()) +// -> unordered_map; +// +// template +// unordered_map(InputIterator, InputIterator, typename see below::size_type, Allocator) +// -> unordered_map, iter-mapped-type, +// hash>, +// equal_to>, Allocator>; +// +// template +// unordered_map(InputIterator, InputIterator, Allocator) +// -> unordered_map, iter-mapped-type, +// hash>, +// equal_to>, Allocator>; +// +// template +// unordered_map(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator) +// -> unordered_map, iter-mapped-type, Hash, +// equal_to>, Allocator>; +// +// template +// unordered_map(initializer_list>, typename see below::size_type, Allocator) +// -> unordered_map, equal_to, Allocator>; +// +// template +// unordered_map(initializer_list>, Allocator) +// -> unordered_map, equal_to, Allocator>; +// +// template +// unordered_map(initializer_list>, typename see below::size_type, Hash, +// Allocator) +// -> unordered_map, Allocator>; + +#include // std::is_permutation +#include +#include // INT_MAX +#include +#include + +#include "test_allocator.h" + +using P = std::pair; +using PC = std::pair; + +int main(int, char**) +{ + const PC expected_m[] = { {1,1L}, {2,2L}, {3,1L}, {INT_MAX,1L} }; + + { + const PC arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::unordered_map m(std::begin(arr), std::end(arr)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const PC arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::unordered_map m(std::begin(arr), std::end(arr), 42); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const PC arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::unordered_map m(std::begin(arr), std::end(arr), 42, std::hash()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const PC arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::unordered_map m(std::begin(arr), std::end(arr), 42, std::hash(), std::equal_to<>()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to<>>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const PC arr[] = { {1,1L}, {2,2L}, {1,1L}, {INT_MAX,1L}, {3,1L} }; + std::unordered_map m(std::begin(arr), std::end(arr), 42, std::hash(), std::equal_to<>(), test_allocator(0, 41)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to<>, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 41); + } + + { + std::unordered_map m { PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }; + ASSERT_SAME_TYPE(decltype(m), std::unordered_map); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_map m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, 42); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_map m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, 42, std::hash()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_map m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, 42, std::hash(), std::equal_to<>()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to<>>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_map m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, 42, std::hash(), std::equal_to<>(), test_allocator(0, 44)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to<>, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 44); + } + + { + const PC arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_map m(std::begin(arr), std::end(arr), 42, test_allocator(0, 45)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 45); + } + + { + const PC arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_map m(std::begin(arr), std::end(arr), 42, std::hash(), test_allocator(0, 46)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 46); + } + + { + std::unordered_map m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, 42, test_allocator(0, 47)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 47); + } + + { + std::unordered_map m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, 42, std::hash(), test_allocator(0, 48)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_map, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 48); + } + + return 0; +} diff --git a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.fail.cpp b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.fail.cpp new file mode 100644 index 00000000000000..7f170472d7a521 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.fail.cpp @@ -0,0 +1,106 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides +// XFAIL: clang-6, apple-clang-9.0, apple-clang-9.1, apple-clang-10.0 + +// template>, +// class Pred = equal_to>, +// class Allocator = allocator>> +// unordered_multimap(InputIterator, InputIterator, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_multimap, iter-mapped-type, Hash, Pred, +// Allocator>; +// +// template, +// class Pred = equal_to, class Allocator = allocator>> +// unordered_multimap(initializer_list>, +// typename see below::size_type = see below, Hash = Hash(), +// Pred = Pred(), Allocator = Allocator()) +// -> unordered_multimap; +// +// template +// unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Allocator) +// -> unordered_multimap, iter-mapped-type, +// hash>, +// equal_to>, Allocator>; +// +// template +// unordered_multimap(InputIterator, InputIterator, Allocator) +// -> unordered_multimap, iter-mapped-type, +// hash>, +// equal_to>, Allocator>; +// +// template +// unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator) +// -> unordered_multimap, iter-mapped-type, Hash, +// equal_to>, Allocator>; +// +// template +// unordered_multimap(initializer_list>, typename see below::size_type, Allocator) +// -> unordered_multimap, equal_to, Allocator>; +// +// template +// unordered_multimap(initializer_list>, Allocator) +// -> unordered_multimap, equal_to, Allocator>; +// +// template +// unordered_multimap(initializer_list>, typename see below::size_type, Hash, +// Allocator) +// -> unordered_multimap, Allocator>; + +#include +#include + +int main(int, char**) +{ + using P = std::pair; + { + // cannot deduce Key from nothing + std::unordered_multimap m; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multimap'}} + } + { + // cannot deduce Key from just (Size) + std::unordered_multimap m(42); // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multimap'}} + } + { + // cannot deduce Key from just (Size, Hash) + std::unordered_multimap m(42, std::hash()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multimap'}} + } + { + // cannot deduce Key from just (Size, Hash, Pred) + std::unordered_multimap m(42, std::hash(), std::equal_to()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multimap'}} + } + { + // cannot deduce Key from just (Size, Hash, Pred, Allocator) + std::unordered_multimap m(42, std::hash(), std::equal_to(), std::allocator

    ()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multimap'}} + } + { + // cannot deduce Key from just (Allocator) + std::unordered_multimap m(std::allocator

    {}); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multimap'}} + } + { + // cannot deduce Key from just (Size, Allocator) + std::unordered_multimap m(42, std::allocator

    ()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multimap'}} + } + { + // cannot deduce Key from just (Size, Hash, Allocator) + std::unordered_multimap m(42, std::hash(), std::allocator

    ()); + // expected-error@-1{{no viable constructor or deduction guide for deduction of template arguments of 'unordered_multimap'}} + } + + return 0; +} diff --git a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp new file mode 100644 index 00000000000000..f620f1e37112c7 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp @@ -0,0 +1,204 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template>, +// class Pred = equal_to>, +// class Allocator = allocator>> +// unordered_multimap(InputIterator, InputIterator, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_multimap, iter-mapped-type, Hash, Pred, +// Allocator>; +// +// template, +// class Pred = equal_to, class Allocator = allocator>> +// unordered_multimap(initializer_list>, +// typename see below::size_type = see below, Hash = Hash(), +// Pred = Pred(), Allocator = Allocator()) +// -> unordered_multimap; +// +// template +// unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Allocator) +// -> unordered_multimap, iter-mapped-type, +// hash>, +// equal_to>, Allocator>; +// +// template +// unordered_multimap(InputIterator, InputIterator, Allocator) +// -> unordered_multimap, iter-mapped-type, +// hash>, +// equal_to>, Allocator>; +// +// template +// unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator) +// -> unordered_multimap, iter-mapped-type, Hash, +// equal_to>, Allocator>; +// +// template +// unordered_multimap(initializer_list>, typename see below::size_type, Allocator) +// -> unordered_multimap, equal_to, Allocator>; +// +// template +// unordered_multimap(initializer_list>, Allocator) +// -> unordered_multimap, equal_to, Allocator>; +// +// template +// unordered_multimap(initializer_list>, typename see below::size_type, Hash, +// Allocator) +// -> unordered_multimap, Allocator>; + +#include // is_permutation +#include +#include // INT_MAX +#include +#include + +#include "test_allocator.h" + +using P = std::pair; +using PC = std::pair; + +int main(int, char**) +{ + const PC expected_m[] = { {1,1}, {1,1}, {2,2}, {3,1}, {INT_MAX,1} }; + + { + const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_multimap m(std::begin(arr), std::end(arr)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_multimap m(std::begin(arr), std::end(arr), 42); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_multimap m(std::begin(arr), std::end(arr), 42, std::hash()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_multimap m(std::begin(arr), std::end(arr), 42, std::hash(), std::equal_to<>()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to<>>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_multimap m(std::begin(arr), std::end(arr), 42, std::hash(), std::equal_to<>(), test_allocator(0, 41)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to<>, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 41); + } + + { + std::unordered_multimap source; + std::unordered_multimap m(source); + ASSERT_SAME_TYPE(decltype(m), decltype(source)); + assert(m.size() == 0); + } + + { + std::unordered_multimap source; + std::unordered_multimap m{source}; // braces instead of parens + ASSERT_SAME_TYPE(decltype(m), decltype(source)); + assert(m.size() == 0); + } + + { + std::unordered_multimap, std::equal_to<>, test_allocator> source; + test_allocator a(0, 42); + std::unordered_multimap m(source, a); + ASSERT_SAME_TYPE(decltype(m), decltype(source)); + assert(m.get_allocator().get_id() == 42); + assert(m.size() == 0); + } + + { + std::unordered_multimap, std::equal_to<>, test_allocator> source; + test_allocator a(0, 43); + std::unordered_multimap m{source, a}; // braces instead of parens + ASSERT_SAME_TYPE(decltype(m), decltype(source)); + assert(m.get_allocator().get_id() == 43); + assert(m.size() == 0); + } + + { + std::unordered_multimap m { P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }; + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_multimap m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_multimap m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42, std::hash()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_multimap m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42, std::hash(), std::equal_to<>()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to<>>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_multimap m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42, std::hash(), std::equal_to<>(), test_allocator(0, 44)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to<>, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 44); + } + + { + const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_multimap m(std::begin(arr), std::end(arr), 42, test_allocator(0, 45)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 45); + } + + { + const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_multimap m(std::begin(arr), std::end(arr), 42, std::hash(), test_allocator(0, 46)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 46); + } + + { + std::unordered_multimap m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42, test_allocator(0, 47)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 47); + } + + { + std::unordered_multimap m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42, std::hash(), test_allocator(0, 48)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 48); + } + + return 0; +} diff --git a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct_const.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct_const.pass.cpp new file mode 100644 index 00000000000000..8a4a3836411731 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct_const.pass.cpp @@ -0,0 +1,173 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: libcpp-no-deduction-guides + +// template>, +// class Pred = equal_to>, +// class Allocator = allocator>> +// unordered_multimap(InputIterator, InputIterator, typename see below::size_type = see below, +// Hash = Hash(), Pred = Pred(), Allocator = Allocator()) +// -> unordered_multimap, iter-mapped-type, Hash, Pred, +// Allocator>; +// +// template, +// class Pred = equal_to, class Allocator = allocator>> +// unordered_multimap(initializer_list>, +// typename see below::size_type = see below, Hash = Hash(), +// Pred = Pred(), Allocator = Allocator()) +// -> unordered_multimap; +// +// template +// unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Allocator) +// -> unordered_multimap, iter-mapped-type, +// hash>, +// equal_to>, Allocator>; +// +// template +// unordered_multimap(InputIterator, InputIterator, Allocator) +// -> unordered_multimap, iter-mapped-type, +// hash>, +// equal_to>, Allocator>; +// +// template +// unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator) +// -> unordered_multimap, iter-mapped-type, Hash, +// equal_to>, Allocator>; +// +// template +// unordered_multimap(initializer_list>, typename see below::size_type, Allocator) +// -> unordered_multimap, equal_to, Allocator>; +// +// template +// unordered_multimap(initializer_list>, Allocator) +// -> unordered_multimap, equal_to, Allocator>; +// +// template +// unordered_multimap(initializer_list>, typename see below::size_type, Hash, +// Allocator) +// -> unordered_multimap, Allocator>; + +#include // is_permutation +#include +#include // INT_MAX +#include +#include +#include + +#include "test_allocator.h" + +using P = std::pair; +using PC = std::pair; + +int main(int, char**) +{ + const PC expected_m[] = { {1,1}, {1,1}, {2,2}, {3,1}, {INT_MAX,1} }; + + { + const PC arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_multimap m(std::begin(arr), std::end(arr)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const PC arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_multimap m(std::begin(arr), std::end(arr), 42); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const PC arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_multimap m(std::begin(arr), std::end(arr), 42, std::hash()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const PC arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_multimap m(std::begin(arr), std::end(arr), 42, std::hash(), std::equal_to<>()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to<>>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + const PC arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_multimap m(std::begin(arr), std::end(arr), 42, std::hash(), std::equal_to<>(), test_allocator(0, 41)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to<>, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 41); + } + + { + std::unordered_multimap m { PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }; + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_multimap m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, 42); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_multimap m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, 42, std::hash()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_multimap m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, 42, std::hash(), std::equal_to<>()); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to<>>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + } + + { + std::unordered_multimap m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, 42, std::hash(), std::equal_to<>(), test_allocator(0, 44)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to<>, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 44); + } + + { + const PC arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_multimap m(std::begin(arr), std::end(arr), 42, test_allocator(0, 45)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 45); + } + + { + const PC arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; + std::unordered_multimap m(std::begin(arr), std::end(arr), 42, std::hash(), test_allocator(0, 46)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 46); + } + + { + std::unordered_multimap m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, 42, test_allocator(0, 47)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 47); + } + + { + std::unordered_multimap m({ PC{1,1L}, PC{2,2L}, PC{1,1L}, PC{INT_MAX,1L}, PC{3,1L} }, 42, std::hash(), test_allocator(0, 48)); + ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap, std::equal_to, test_allocator>); + assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); + assert(m.get_allocator().get_id() == 48); + } + + return 0; +} diff --git a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp index 7becaf96009a4e..683d2019764145 100644 --- a/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.multiset/unord.multiset.cnstr/deduct.pass.cpp @@ -9,6 +9,7 @@ // // UNSUPPORTED: c++98, c++03, c++11, c++14 // UNSUPPORTED: libcpp-no-deduction-guides +// UNSUPPORTED: apple-clang-9.1 // template>, diff --git a/libcxx/test/std/containers/unord/unord.set/contains.pass.cpp b/libcxx/test/std/containers/unord/unord.set/contains.pass.cpp new file mode 100644 index 00000000000000..3b87f2fd0e04da --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.set/contains.pass.cpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +#include +#include + +// + +// bool contains(const key_type& x) const; + +template +void test(B bad, Vals... args) { + T set; + V vals[] = {args...}; + + for (auto& v : vals) set.insert(v); + for (auto& v : vals) assert(set.contains(v)); + + assert(!set.contains(bad)); +} + +struct E { int a = 1; double b = 1; char c = 1; }; + +int main(int, char**) +{ + { + test, int>(14, 10, 11, 12, 13); + test, char>('e', 'a', 'b', 'c', 'd'); + } + { + test, int>(14, 10, 11, 12, 13); + test, char>('e', 'a', 'b', 'c', 'd'); + } + + return 0; +} + diff --git a/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp index 20799823692a50..95bc08293f5370 100644 --- a/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.set/unord.set.cnstr/deduct.pass.cpp @@ -9,6 +9,7 @@ // // UNSUPPORTED: c++98, c++03, c++11, c++14 // UNSUPPORTED: libcpp-no-deduction-guides +// UNSUPPORTED: apple-clang-9.1 // template>, diff --git a/libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp b/libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp index 834222c06bfc04..fa4e77c71f7594 100644 --- a/libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp @@ -52,10 +52,19 @@ void A::operator delete(A* a, std::destroying_delete_t) { ::operator delete(a); } -#ifndef __cpp_lib_destroying_delete -#error "Expected __cpp_lib_destroying_delete to be defined" -#elif __cpp_lib_destroying_delete < 201806L -#error "Unexpected value of __cpp_lib_destroying_delete" +// Only test the definition of the library feature-test macro when the compiler +// supports the feature -- otherwise we don't define the library feature-test +// macro. +#if defined(__cpp_impl_destroying_delete) +# if !defined(__cpp_lib_destroying_delete) +# error "Expected __cpp_lib_destroying_delete to be defined" +# elif __cpp_lib_destroying_delete < 201806L +# error "Unexpected value of __cpp_lib_destroying_delete" +# endif +#else +# if defined(__cpp_lib_destroying_delete) +# error "The library feature-test macro for destroying delete shouldn't be defined when the compiler doesn't support the language feature" +# endif #endif int main() { diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp index 41f73328ab7b0d..89f67a227bd1fe 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/convert_copy.pass.cpp @@ -31,6 +31,15 @@ struct Implicit { Implicit(int x) : value(x) {} }; +struct ExplicitTwo { + ExplicitTwo() {} + ExplicitTwo(ExplicitTwo const&) {} + ExplicitTwo(ExplicitTwo &&) {} + + template ::value>::type> + explicit ExplicitTwo(T) {} +}; + struct B { int id_; @@ -136,6 +145,13 @@ int main(int, char**) std::tuple t2 = t1; assert(std::get<0>(t2).value == 42); } + { + static_assert(std::is_convertible::value, ""); + static_assert(std::is_convertible&&, const std::tuple&>::value, ""); + ExplicitTwo e; + std::tuple t = std::tuple(std::move(e)); + ((void)t); + } return 0; } diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp index 55f8d11c1159b8..42a31f3345075a 100644 --- a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp @@ -177,10 +177,34 @@ void test_T_ctor_basic() { #endif } +struct BoomOnAnything { + template + constexpr BoomOnAnything(T) { static_assert(!std::is_same::value, ""); } +}; + +void test_no_narrowing_check_for_class_types() { + using V = std::variant; + V v(42); + assert(v.index() == 0); + assert(std::get<0>(v) == 42); +} + +struct Bar {}; +struct Baz {}; +void test_construction_with_repeated_types() { + using V = std::variant; + static_assert(!std::is_constructible::value, ""); + static_assert(!std::is_constructible::value, ""); + // OK, the selected type appears only once and so it shouldn't + // be affected by the duplicate types. + static_assert(std::is_constructible::value, ""); +} + int main(int, char**) { test_T_ctor_basic(); test_T_ctor_noexcept(); test_T_ctor_sfinae(); - + test_no_narrowing_check_for_class_types(); + test_construction_with_repeated_types(); return 0; } diff --git a/libcxx/www/cxx2a_status.html b/libcxx/www/cxx2a_status.html index b800ef07bfad94..9489c07ef0bbec 100644 --- a/libcxx/www/cxx2a_status.html +++ b/libcxx/www/cxx2a_status.html @@ -83,7 +83,7 @@

    Paper Status

    P0019R8LWGAtomic RefRapperswil - P0458R2LWGChecking for Existence of an Element in Associative ContainersRapperswil + P0458R2LWGChecking for Existence of an Element in Associative ContainersRapperswilComplete P0475R1LWGLWG 2511: guaranteed copy elision for piecewise constructionRapperswil P0476R2LWGBit-casting object representationsRapperswil P0528R3CWGThe Curious Case of Padding Bits, Featuring Atomic Compare-and-ExchangeRapperswil @@ -283,7 +283,7 @@

    Library Working group Issues Status

    2996Missing rvalue overloads for shared_ptr operationsSan Diego 3008make_shared (sub)object destruction semantics are not specifiedSan Diego 3022is_convertible<derived*, base*> may lead to ODRSan DiegoResolved by 1285R0 - 3025Map-like container deduction guides should use pair<Key, T>, not pair<const Key, T>San Diego + 3025Map-like container deduction guides should use pair<Key, T>, not pair<const Key, T>San DiegoComplete 3031Algorithms and predicates with non-const reference argumentsSan Diego 3037polymorphic_allocator and incomplete typesSan Diego 3038polymorphic_allocator::allocate should not allow integer overflow to create vulnerabilitiesSan Diego diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt index 8ca169065f48e9..ce69fff1370a0c 100644 --- a/libcxxabi/CMakeLists.txt +++ b/libcxxabi/CMakeLists.txt @@ -21,7 +21,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBCXXABI_STANDALONE_B project(libcxxabi CXX C) set(PACKAGE_NAME libcxxabi) - set(PACKAGE_VERSION 9.0.0svn) + set(PACKAGE_VERSION 9.0.0) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") diff --git a/libunwind/CMakeLists.txt b/libunwind/CMakeLists.txt index b51922a48fe288..836b286523ef18 100644 --- a/libunwind/CMakeLists.txt +++ b/libunwind/CMakeLists.txt @@ -83,7 +83,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBUNWIND_STANDALONE_B endif() set(PACKAGE_NAME libunwind) - set(PACKAGE_VERSION 9.0.0svn) + set(PACKAGE_VERSION 9.0.0) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index 374751ad510ac8..0e43d2b478b405 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -31,10 +31,10 @@ namespace coff { SectionChunk::SectionChunk(ObjFile *f, const coff_section *h) : Chunk(SectionKind), file(f), header(h), repl(this) { - // Initialize Relocs. + // Initialize relocs. setRelocs(file->getCOFFObj()->getRelocations(header)); - // Initialize SectionName. + // Initialize sectionName. StringRef sectionName; if (Expected e = file->getCOFFObj()->getSectionName(header)) sectionName = *e; @@ -218,7 +218,7 @@ void applyArm64Addr(uint8_t *off, uint64_t s, uint64_t p, int shift) { // Update the immediate field in a AARCH64 ldr, str, and add instruction. // Optionally limit the range of the written immediate by one or more bits -// (RangeLimit). +// (rangeLimit). void applyArm64Imm(uint8_t *off, uint64_t imm, uint32_t rangeLimit) { uint32_t orig = read32le(off); imm += (orig >> 10) & 0xFFF; @@ -561,7 +561,7 @@ void SectionChunk::getRuntimePseudoRelocs( toString(file)); continue; } - // SizeInBits is used to initialize the Flags field; currently no + // sizeInBits is used to initialize the Flags field; currently no // other flags are defined. res.emplace_back( RuntimePseudoReloc(target, this, rel.VirtualAddress, sizeInBits)); diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index f7c80971476548..1b0e2404271033 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -49,7 +49,7 @@ struct Export { // If an export is a form of /export:foo=dllname.bar, that means // that foo should be exported as an alias to bar in the DLL. - // ForwardTo is set to "dllname.bar" part. Usually empty. + // forwardTo is set to "dllname.bar" part. Usually empty. StringRef forwardTo; StringChunk *forwardChunk = nullptr; @@ -132,6 +132,7 @@ struct Configuration { GuardCFLevel guardCF = GuardCFLevel::Off; // Used for SafeSEH. + bool safeSEH = false; Symbol *sehTable = nullptr; Symbol *sehCount = nullptr; diff --git a/lld/COFF/DLL.cpp b/lld/COFF/DLL.cpp index 932e7d64553ec6..40d1f463aa3fff 100644 --- a/lld/COFF/DLL.cpp +++ b/lld/COFF/DLL.cpp @@ -567,7 +567,7 @@ void IdataContents::create() { // Create .idata contents for each DLL. for (std::vector &syms : v) { // Create lookup and address tables. If they have external names, - // we need to create HintName chunks to store the names. + // we need to create hintName chunks to store the names. // If they don't (if they are import-by-ordinals), we store only // ordinal values to the table. size_t base = lookups.size(); diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index d003937825bcd2..d7af50b9318fc4 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -936,7 +936,7 @@ static void findKeepUniqueSections() { } } -// link.exe replaces each %foo% in AltPath with the contents of environment +// link.exe replaces each %foo% in altPath with the contents of environment // variable foo, and adds the two magic env vars _PDB (expands to the basename // of pdb's output path) and _EXT (expands to the extension of the output // binary). @@ -952,9 +952,9 @@ static void parsePDBAltPath(StringRef altPath) { binaryExtension = binaryExtension.substr(1); // %_EXT% does not include '.'. // Invariant: - // +--------- Cursor ('a...' might be the empty string). - // | +----- FirstMark - // | | +- SecondMark + // +--------- cursor ('a...' might be the empty string). + // | +----- firstMark + // | | +- secondMark // v v v // a...%...%... size_t cursor = 0; @@ -1556,6 +1556,11 @@ void LinkerDriver::link(ArrayRef argsArr) { } config->wordsize = config->is64() ? 8 : 4; + // Handle /safeseh, x86 only, on by default, except for mingw. + if (config->machine == I386 && + args.hasFlag(OPT_safeseh, OPT_safeseh_no, !config->mingw)) + config->safeSEH = true; + // Handle /functionpadmin for (auto *arg : args.filtered(OPT_functionpadmin, OPT_functionpadmin_opt)) parseFunctionPadMin(arg, config->machine); @@ -1606,7 +1611,7 @@ void LinkerDriver::link(ArrayRef argsArr) { // Handle generation of import library from a def file. if (!args.hasArg(OPT_INPUT)) { fixupExports(); - createImportLibrary(/*AsLib=*/true); + createImportLibrary(/*asLib=*/true); return; } @@ -1795,15 +1800,6 @@ void LinkerDriver::link(ArrayRef argsArr) { if (errorCount()) return; - // Handle /safeseh. - if (args.hasFlag(OPT_safeseh, OPT_safeseh_no, false)) { - for (ObjFile *file : ObjFile::instances) - if (!file->hasSafeSEH()) - error("/safeseh: " + file->getName() + " is not compatible with SEH"); - if (errorCount()) - return; - } - if (config->mingw) { // In MinGW, all symbols are automatically exported if no symbols // are chosen to be exported. @@ -1830,7 +1826,7 @@ void LinkerDriver::link(ArrayRef argsArr) { // need to create a .lib file. if (!config->exports.empty() || config->dll) { fixupExports(); - createImportLibrary(/*AsLib=*/false); + createImportLibrary(/*asLib=*/false); assignExportOrdinals(); } diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index 59bdaec2edd8bc..4360ac23b26228 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -345,10 +345,10 @@ class TemporaryFile { // so it is safe to remove the file immediately after this function // is called (you cannot remove an opened file on Windows.) std::unique_ptr getMemoryBuffer() { - // IsVolatileSize=true forces MemoryBuffer to not use mmap(). + // IsVolatile=true forces MemoryBuffer to not use mmap(). return CHECK(MemoryBuffer::getFile(path, /*FileSize=*/-1, /*RequiresNullTerminator=*/false, - /*IsVolatileSize=*/true), + /*IsVolatile=*/true), "could not open " + path); } diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp index 9936a6f69ffed4..c00d5c5b494ef9 100644 --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -556,8 +556,8 @@ Optional ObjFile::createDefined( // The second symbol entry has the name of the comdat symbol, called the // "comdat leader". // When this function is called for the first symbol entry of a comdat, - // it sets ComdatDefs and returns None, and when it's called for the second - // symbol entry it reads ComdatDefs and then sets it back to nullptr. + // it sets comdatDefs and returns None, and when it's called for the second + // symbol entry it reads comdatDefs and then sets it back to nullptr. // Handle comdat leader. if (const coff_aux_section_definition *def = comdatDefs[sectionNumber]) { @@ -626,7 +626,7 @@ ArrayRef ObjFile::getDebugSection(StringRef secName) { // even if the TU was compiled with no debug info. At least two records are // always there. S_OBJNAME stores a 32-bit signature, which is loaded into the // PCHSignature member. S_COMPILE3 stores compile-time cmd-line flags. This is -// currently used to initialize the HotPatchable member. +// currently used to initialize the hotPatchable member. void ObjFile::initializeFlags() { ArrayRef data = getDebugSection(".debug$S"); if (data.empty()) @@ -764,7 +764,7 @@ void ImportFile::parse() { impSym = symtab->addImportData(impName, this); // If this was a duplicate, we logged an error but may continue; - // in this case, ImpSym is nullptr. + // in this case, impSym is nullptr. if (!impSym) return; diff --git a/lld/COFF/InputFiles.h b/lld/COFF/InputFiles.h index 6c84ceec13dbd3..dfad9814a397d8 100644 --- a/lld/COFF/InputFiles.h +++ b/lld/COFF/InputFiles.h @@ -119,7 +119,7 @@ class ObjFile : public InputFile { ArrayRef getDebugSection(StringRef secName); - // Returns a Symbol object for the SymbolIndex'th symbol in the + // Returns a Symbol object for the symbolIndex'th symbol in the // underlying object file. Symbol *getSymbol(uint32_t symbolIndex) { return symbols[symbolIndex]; diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp index d024f7573f3da5..a55e5136e040b6 100644 --- a/lld/COFF/PDB.cpp +++ b/lld/COFF/PDB.cpp @@ -119,7 +119,7 @@ class PDBLinker { /// /// If the object does not use a type server PDB (compiled with /Z7), we merge /// all the type and item records from the .debug$S stream and fill in the - /// caller-provided ObjectIndexMap. + /// caller-provided objectIndexMap. Expected mergeDebugT(ObjFile *file, CVIndexMap *objectIndexMap); @@ -683,7 +683,7 @@ static void translateIdSymbols(MutableArrayRef &recordData, TypeIndex *ti = reinterpret_cast(content.data() + refs[0].Offset); - // `TI` is the index of a FuncIdRecord or MemberFuncIdRecord which lives in + // `ti` is the index of a FuncIdRecord or MemberFuncIdRecord which lives in // the IPI stream, whose `FunctionType` member refers to the TPI stream. // Note that LF_FUNC_ID and LF_MEMFUNC_ID have the same record layout, and // in both cases we just need the second type index. @@ -1729,7 +1729,7 @@ static bool findLineTable(const SectionChunk *c, uint32_t addr, if (dbgC->getSectionName() != ".debug$S") continue; - // Build a mapping of SECREL relocations in DbgC that refer to C. + // Build a mapping of SECREL relocations in dbgC that refer to `c`. DenseMap secrels; for (const coff_relocation &r : dbgC->getRelocs()) { if (r.Type != secrelReloc) diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index 280a9c28892c87..0aff164ee56778 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -69,7 +69,7 @@ static Symbol *getSymbol(SectionChunk *sc, uint32_t addr) { for (Symbol *s : sc->file->getSymbols()) { auto *d = dyn_cast_or_null(s); - if (!d || d->getChunk() != sc || d->getValue() > addr || + if (!d || !d->data || d->getChunk() != sc || d->getValue() > addr || (candidate && d->getValue() < candidate->getValue())) continue; @@ -192,7 +192,7 @@ bool SymbolTable::handleMinGWAutomaticImport(Symbol *sym, StringRef name) { // Replace the reference directly to a variable with a reference // to the import address table instead. This obviously isn't right, - // but we mark the symbol as IsRuntimePseudoReloc, and a later pass + // but we mark the symbol as isRuntimePseudoReloc, and a later pass // will add runtime pseudo relocations for every relocation against // this Symbol. The runtime pseudo relocation framework expects the // reference itself to point at the IAT entry. diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h index 75bd3933547b0a..88f47cbe9e78a8 100644 --- a/lld/COFF/SymbolTable.h +++ b/lld/COFF/SymbolTable.h @@ -112,7 +112,7 @@ class SymbolTable { private: /// Inserts symbol if not already present. std::pair insert(StringRef name); - /// Same as insert(Name), but also sets IsUsedInRegularObj. + /// Same as insert(Name), but also sets isUsedInRegularObj. std::pair insert(StringRef name, InputFile *f); std::vector getSymsWithPrefix(StringRef prefix); diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 46b1af0934ab3d..36ef87de4263e5 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -335,7 +335,7 @@ void OutputSection::addContributingPartialSection(PartialSection *sec) { } // namespace lld // Check whether the target address S is in range from a relocation -// of type RelType at address P. +// of type relType at address P. static bool isInRange(uint16_t relType, uint64_t s, uint64_t p, int margin) { if (config->machine == ARMNT) { int64_t diff = AbsoluteDifference(s, p + 4) + margin; @@ -427,7 +427,7 @@ static bool createThunks(OutputSection *os, int margin) { // The estimate of the source address P should be pretty accurate, // but we don't know whether the target Symbol address should be - // offset by ThunkSize or not (or by some of ThunksSize but not all of + // offset by thunksSize or not (or by some of thunksSize but not all of // it), giving us some uncertainty once we have added one thunk. uint64_t p = sc->getRVA() + rel.VirtualAddress + thunksSize; @@ -917,7 +917,7 @@ void Writer::createMiscChunks() { } // Create SEH table. x86-only. - if (config->machine == I386) + if (config->safeSEH) createSEHTable(); // Create /guard:cf tables if requested. @@ -1428,23 +1428,15 @@ void Writer::openFile(StringRef path) { } void Writer::createSEHTable() { - // Set the no SEH characteristic on x86 binaries unless we find exception - // handlers. - setNoSEHCharacteristic = true; - SymbolRVASet handlers; for (ObjFile *file : ObjFile::instances) { - // FIXME: We should error here instead of earlier unless /safeseh:no was - // passed. if (!file->hasSafeSEH()) - return; - + error("/safeseh: " + file->getName() + " is not compatible with SEH"); markSymbolsForRVATable(file, file->getSXDataChunks(), handlers); } - // Remove the "no SEH" characteristic if all object files were built with - // safeseh, we found some exception handlers, and there is a load config in - // the object. + // Set the "no SEH" characteristic if there really were no handlers, or if + // there is no load config object to point to the table of handlers. setNoSEHCharacteristic = handlers.empty() || !symtab->findUnderscore("_load_config_used"); @@ -1626,7 +1618,7 @@ void Writer::markSymbolsForRVATable(ObjFile *file, } // Replace the absolute table symbol with a synthetic symbol pointing to -// TableChunk so that we can emit base relocations for it and resolve section +// tableChunk so that we can emit base relocations for it and resolve section // relative relocations. void Writer::maybeAddRVATable(SymbolRVASet tableSymbols, StringRef tableSym, StringRef countSym) { diff --git a/lld/Common/ErrorHandler.cpp b/lld/Common/ErrorHandler.cpp index f5d3eb44848c52..c87c0609b26018 100644 --- a/lld/Common/ErrorHandler.cpp +++ b/lld/Common/ErrorHandler.cpp @@ -16,6 +16,7 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/raw_ostream.h" #include +#include #if !defined(_MSC_VER) && !defined(__MINGW32__) #include @@ -84,8 +85,42 @@ void lld::checkError(Error e) { [&](ErrorInfoBase &eib) { error(eib.message()); }); } -void ErrorHandler::print(StringRef s, raw_ostream::Colors c) { - *errorOS << logName << ": "; +static std::string getLocation(std::string msg, std::string defaultMsg) { + static std::vector Regexes{ + std::regex(R"(^undefined symbol:.*\n>>> referenced by (\S+):(\d+)\n.*)"), + std::regex(R"(^undefined symbol:.*\n>>> referenced by (.*):)"), + std::regex( + R"(^duplicate symbol: .*\n>>> defined in (\S+)\n>>> defined in.*)"), + std::regex( + R"(^duplicate symbol: .*\n>>> defined at (\S+):(\d+).*)"), + std::regex( + R"(.*\n>>> defined in .*\n>>> referenced by (\S+):(\d+))"), + std::regex( + R"(^undefined (internal|hidden|protected) symbol: .*\n>>> referenced by (\S+):(\d+)\n.*)"), + std::regex(R"((\S+):(\d+): unclosed quote)"), + }; + + std::smatch Match; + for (std::regex &Re : Regexes) { + if (std::regex_search(msg, Match, Re)) { + return Match.size() > 2 ? Match.str(1) + "(" + Match.str(2) + ")" + : Match.str(1); + } + } + return defaultMsg; +} + +void ErrorHandler::printHeader(StringRef s, raw_ostream::Colors c, + const Twine &msg) { + + if (vsDiagnostics) { + // A Visual Studio-style error message starts with an error location. + // If a location cannot be extracted then we default to LogName. + *errorOS << getLocation(msg.str(), logName) << ": "; + } else { + *errorOS << logName << ": "; + } + if (colorDiagnostics) { errorOS->changeColor(c, true); *errorOS << s; @@ -116,7 +151,7 @@ void ErrorHandler::warn(const Twine &msg) { std::lock_guard lock(mu); newline(errorOS, msg); - print("warning: ", raw_ostream::MAGENTA); + printHeader("warning: ", raw_ostream::MAGENTA, msg); *errorOS << msg << "\n"; } @@ -125,10 +160,10 @@ void ErrorHandler::error(const Twine &msg) { newline(errorOS, msg); if (errorLimit == 0 || errorCount < errorLimit) { - print("error: ", raw_ostream::RED); + printHeader("error: ", raw_ostream::RED, msg); *errorOS << msg << "\n"; } else if (errorCount == errorLimit) { - print("error: ", raw_ostream::RED); + printHeader("error: ", raw_ostream::RED, msg); *errorOS << errorLimitExceededMsg << "\n"; if (exitEarly) exitLld(1); diff --git a/lld/ELF/AArch64ErrataFix.cpp b/lld/ELF/AArch64ErrataFix.cpp index 7473ab61c45672..b2eda4dcbc4e98 100644 --- a/lld/ELF/AArch64ErrataFix.cpp +++ b/lld/ELF/AArch64ErrataFix.cpp @@ -413,8 +413,8 @@ void lld::elf::Patch843419Section::writeTo(uint8_t *buf) { write32le(buf, read32le(patchee->data().begin() + patcheeOffset)); // Apply any relocation transferred from the original PatcheeSection. - // For a SyntheticSection Buf already has OutSecOff added, but relocateAlloc - // also adds OutSecOff so we need to subtract to avoid double counting. + // For a SyntheticSection Buf already has outSecOff added, but relocateAlloc + // also adds outSecOff so we need to subtract to avoid double counting. this->relocateAlloc(buf - outSecOff, buf - outSecOff + getSize()); // Return address is the next instruction after the one we have just copied. @@ -427,7 +427,7 @@ void AArch64Err843419Patcher::init() { // The AArch64 ABI permits data in executable sections. We must avoid scanning // this data as if it were instructions to avoid false matches. We use the // mapping symbols in the InputObjects to identify this data, caching the - // results in SectionMap so we don't have to recalculate it each pass. + // results in sectionMap so we don't have to recalculate it each pass. // The ABI Section 4.5.4 Mapping symbols; defines local symbols that describe // half open intervals [Symbol Value, Next Symbol Value) of code and data @@ -489,7 +489,7 @@ void AArch64Err843419Patcher::insertPatches( uint64_t patchUpperBound = prevIsecLimit + target->getThunkSectionSpacing(); uint64_t outSecAddr = isd.sections.front()->getParent()->addr; - // Set the OutSecOff of patches to the place where we want to insert them. + // Set the outSecOff of patches to the place where we want to insert them. // We use a similar strategy to Thunk placement. Place patches roughly // every multiple of maximum branch range. auto patchIt = patches.begin(); @@ -511,10 +511,10 @@ void AArch64Err843419Patcher::insertPatches( (*patchIt)->outSecOff = isecLimit; } - // merge all patch sections. We use the OutSecOff assigned above to + // merge all patch sections. We use the outSecOff assigned above to // determine the insertion point. This is ok as we only merge into an // InputSectionDescription once per pass, and at the end of the pass - // assignAddresses() will recalculate all the OutSecOff values. + // assignAddresses() will recalculate all the outSecOff values. std::vector tmp; tmp.reserve(isd.sections.size() + patches.size()); auto mergeCmp = [](const InputSection *a, const InputSection *b) { @@ -530,8 +530,8 @@ void AArch64Err843419Patcher::insertPatches( isd.sections = std::move(tmp); } -// Given an erratum sequence that starts at address AdrpAddr, with an -// instruction that we need to patch at PatcheeOffset from the start of +// Given an erratum sequence that starts at address adrpAddr, with an +// instruction that we need to patch at patcheeOffset from the start of // InputSection IS, create a Patch843419 Section and add it to the // Patches that we need to insert. static void implementPatch(uint64_t adrpAddr, uint64_t patcheeOffset, @@ -587,10 +587,10 @@ AArch64Err843419Patcher::patchInputSectionDescription( // LLD doesn't use the erratum sequence in SyntheticSections. if (isa(isec)) continue; - // Use SectionMap to make sure we only scan code and not inline data. + // Use sectionMap to make sure we only scan code and not inline data. // We have already sorted MapSyms in ascending order and removed consecutive // mapping symbols of the same type. Our range of executable instructions to - // scan is therefore [CodeSym->Value, DataSym->Value) or [CodeSym->Value, + // scan is therefore [codeSym->value, dataSym->value) or [codeSym->value, // section size). std::vector &mapSyms = sectionMap[isec]; diff --git a/lld/ELF/AArch64ErrataFix.h b/lld/ELF/AArch64ErrataFix.h index e4752e7bb8a9c7..0548b58751ff94 100644 --- a/lld/ELF/AArch64ErrataFix.h +++ b/lld/ELF/AArch64ErrataFix.h @@ -36,7 +36,7 @@ class AArch64Err843419Patcher { void init(); - // A cache of the mapping symbols defined by the InputSecion sorted in order + // A cache of the mapping symbols defined by the InputSection sorted in order // of ascending value with redundant symbols removed. These describe // the ranges of code and data in an executable InputSection. std::map> sectionMap; diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 9b6599be38fc10..4d4789702f03d3 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -517,7 +517,7 @@ void AArch64BtiPac::writePltHeader(uint8_t *buf) const { uint64_t plt = in.plt->getVA(); if (btiHeader) { - // PltHeader is called indirectly by Plt[N]. Prefix PltData with a BTI C + // PltHeader is called indirectly by plt[N]. Prefix pltData with a BTI C // instruction. memcpy(buf, btiData, sizeof(btiData)); buf += sizeof(btiData); @@ -538,7 +538,7 @@ void AArch64BtiPac::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr, int32_t index, unsigned relOff) const { // The PLT entry is of the form: - // [BtiData] AddrInst (PacBr | StdBr) [NopData] + // [btiData] addrInst (pacBr | stdBr) [nopData] const uint8_t btiData[] = { 0x5f, 0x24, 0x03, 0xd5 }; // bti c const uint8_t addrInst[] = { 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[n])) diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp index b69974fc72c677..64adc33c07ae28 100644 --- a/lld/ELF/Arch/ARM.cpp +++ b/lld/ELF/Arch/ARM.cpp @@ -299,13 +299,13 @@ bool ARM::needsThunk(RelExpr expr, RelType type, const InputFile *file, uint32_t ARM::getThunkSectionSpacing() const { // The placing of pre-created ThunkSections is controlled by the value - // ThunkSectionSpacing returned by getThunkSectionSpacing(). The aim is to + // thunkSectionSpacing returned by getThunkSectionSpacing(). The aim is to // place the ThunkSection such that all branches from the InputSections // prior to the ThunkSection can reach a Thunk placed at the end of the // ThunkSection. Graphically: - // | up to ThunkSectionSpacing .text input sections | + // | up to thunkSectionSpacing .text input sections | // | ThunkSection | - // | up to ThunkSectionSpacing .text input sections | + // | up to thunkSectionSpacing .text input sections | // | ThunkSection | // Pre-created ThunkSections are spaced roughly 16MiB apart on ARMv7. This @@ -316,14 +316,14 @@ uint32_t ARM::getThunkSectionSpacing() const { // Thumb B.W range +/- 1MiB // If a branch cannot reach a pre-created ThunkSection a new one will be // created so we can handle the rare cases of a Thumb 2 conditional branch. - // We intentionally use a lower size for ThunkSectionSpacing than the maximum + // We intentionally use a lower size for thunkSectionSpacing than the maximum // branch range so the end of the ThunkSection is more likely to be within // range of the branch instruction that is furthest away. The value we shorten - // ThunkSectionSpacing by is set conservatively to allow us to create 16,384 + // thunkSectionSpacing by is set conservatively to allow us to create 16,384 // 12 byte Thunks at any offset in a ThunkSection without risk of a branch to // one of the Thunks going out of range. - // On Arm the ThunkSectionSpacing depends on the range of the Thumb Branch + // On Arm the thunkSectionSpacing depends on the range of the Thumb Branch // range. On earlier Architectures such as ARMv4, ARMv5 and ARMv6 (except // ARMv6T2) the range is +/- 4MiB. diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index 96b829101f8d3d..70d284cfad7131 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -946,6 +946,7 @@ void PPC64::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const { // addis rT, r2, sym@got@tprel@ha. relocateOne(loc, R_PPC64_GOT_TPREL16_HA, val); return; + case R_PPC64_GOT_TLSGD16: case R_PPC64_GOT_TLSGD16_LO: { // Relax from addi r3, rA, sym@got@tlsgd@l to // ld r3, sym@got@tprel@l(rA) diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp index ddd9b9f7e5cd43..6f16ade5717731 100644 --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -144,7 +144,7 @@ void RISCV::writePltHeader(uint8_t *buf) const { // 1: auipc t2, %pcrel_hi(.got.plt) // sub t1, t1, t3 // l[wd] t3, %pcrel_lo(1b)(t2); t3 = _dl_runtime_resolve - // addi t1, t1, -PltHeaderSize-12; t1 = &.plt[i] - &.plt[0] + // addi t1, t1, -pltHeaderSize-12; t1 = &.plt[i] - &.plt[0] // addi t0, t2, %pcrel_lo(1b) // srli t1, t1, (rv64?1:2); t1 = &.got.plt[i] - &.got.plt[0] // l[wd] t0, Wordsize(t0); t0 = link_map diff --git a/lld/ELF/CallGraphSort.cpp b/lld/ELF/CallGraphSort.cpp index c9a62f69accad6..9aaadd4818336b 100644 --- a/lld/ELF/CallGraphSort.cpp +++ b/lld/ELF/CallGraphSort.cpp @@ -177,7 +177,7 @@ void CallGraphSort::groupClusters() { }); for (int si : sortedSecs) { - // Clusters[SI] is the same as SecToClusters[SI] here because it has not + // clusters[si] is the same as secToClusters[si] here because it has not // been merged into another cluster yet. Cluster &c = clusters[si]; @@ -233,8 +233,8 @@ DenseMap CallGraphSort::run() { return orderMap; } - // Print the symbols ordered by C3, in the order of increasing CurOrder - // Instead of sorting all the OrderMap, just repeat the loops above. + // Print the symbols ordered by C3, in the order of increasing curOrder + // Instead of sorting all the orderMap, just repeat the loops above. for (const Cluster &c : clusters) for (int secIndex : c.sections) // Search all the symbols in the file of the section diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 54991c7277829b..ff9d3dc0933c0b 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -249,7 +249,7 @@ struct Configuration { // True if the target is little-endian. False if big-endian. bool isLE; - // endianness::little if IsLE is true. endianness::big otherwise. + // endianness::little if isLE is true. endianness::big otherwise. llvm::support::endianness endianness; // True if the target is the little-endian MIPS64. diff --git a/lld/ELF/DWARF.cpp b/lld/ELF/DWARF.cpp index ab06d066b0793e..1e4b36f71b5406 100644 --- a/lld/ELF/DWARF.cpp +++ b/lld/ELF/DWARF.cpp @@ -110,7 +110,8 @@ LLDDwarfObj::findAux(const InputSectionBase &sec, uint64_t pos, DataRefImpl d; d.p = getAddend(rel); return RelocAddrEntry{secIndex, RelocationRef(d, nullptr), - LLDRelocationResolver::resolve, val}; + val, Optional(), + 0, LLDRelocationResolver::resolve}; } template diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index f4f52b4b6fa2f3..fbfc71d22b7e5f 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -272,7 +272,7 @@ void LinkerDriver::addFile(StringRef path, bool withLOption) { // Add a given library by searching it from input search paths. void LinkerDriver::addLibrary(StringRef name) { if (Optional path = searchLibrary(name)) - addFile(*path, /*WithLOption=*/true); + addFile(*path, /*withLOption=*/true); else error("unable to find library -l" + name); } @@ -786,6 +786,8 @@ static void readConfigs(opt::InputArgList &args) { errorHandler().verbose = args.hasArg(OPT_verbose); errorHandler().fatalWarnings = args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); + errorHandler().vsDiagnostics = + args.hasArg(OPT_visual_studio_diagnostics_format, false); threadsEnabled = args.hasFlag(OPT_threads, OPT_no_threads, true); config->allowMultipleDefinition = @@ -1118,7 +1120,7 @@ void LinkerDriver::createFiles(opt::InputArgList &args) { addLibrary(arg->getValue()); break; case OPT_INPUT: - addFile(arg->getValue(), /*WithLOption=*/false); + addFile(arg->getValue(), /*withLOption=*/false); break; case OPT_defsym: { StringRef from; @@ -1255,7 +1257,7 @@ static uint64_t getCommonPageSize(opt::InputArgList &args) { warn("-z common-page-size set, but paging disabled by omagic or nmagic"); return 1; } - // CommonPageSize can't be larger than MaxPageSize. + // commonPageSize can't be larger than maxPageSize. if (val > config->maxPageSize) val = config->maxPageSize; return val; @@ -1263,7 +1265,7 @@ static uint64_t getCommonPageSize(opt::InputArgList &args) { // Parses -image-base option. static Optional getImageBase(opt::InputArgList &args) { - // Because we are using "Config->MaxPageSize" here, this function has to be + // Because we are using "Config->maxPageSize" here, this function has to be // called after the variable is initialized. auto *arg = args.getLastArg(OPT_image_base); if (!arg) @@ -1386,7 +1388,7 @@ static void replaceCommonSymbols() { bss->markDead(); inputSections.push_back(bss); s->replace(Defined{s->file, s->getName(), s->binding, s->stOther, s->type, - /*Value=*/0, s->size, bss}); + /*value=*/0, s->size, bss}); }); } @@ -1406,8 +1408,8 @@ static void demoteSharedSymbols() { }); } -// The section referred to by S is considered address-significant. Set the -// KeepUnique flag on the section if appropriate. +// The section referred to by `s` is considered address-significant. Set the +// keepUnique flag on the section if appropriate. static void markAddrsig(Symbol *s) { if (auto *d = dyn_cast_or_null(s)) if (d->section) @@ -1540,7 +1542,7 @@ template void LinkerDriver::compileBitcodeFiles() { for (InputFile *file : lto->compile()) { auto *obj = cast>(file); - obj->parse(/*IgnoreComdats=*/true); + obj->parse(/*ignoreComdats=*/true); for (Symbol *sym : obj->getGlobalSymbols()) sym->parseSymbolVersion(); objectFiles.push_back(file); @@ -1772,7 +1774,7 @@ template void LinkerDriver::link(opt::InputArgList &args) { if (args.hasArg(OPT_exclude_libs)) excludeLibs(args); - // Create ElfHeader early. We need a dummy section in + // Create elfHeader early. We need a dummy section in // addReservedSymbols to mark the created symbols as not absolute. Out::elfHeader = make("", 0, SHF_ALLOC); Out::elfHeader->size = sizeof(typename ELFT::Ehdr); @@ -1854,14 +1856,14 @@ template void LinkerDriver::link(opt::InputArgList &args) { target = getTarget(); config->eflags = target->calcEFlags(); - // MaxPageSize (sometimes called abi page size) is the maximum page size that + // maxPageSize (sometimes called abi page size) is the maximum page size that // the output can be run on. For example if the OS can use 4k or 64k page - // sizes then MaxPageSize must be 64 for the output to be useable on both. + // sizes then maxPageSize must be 64k for the output to be useable on both. // All important alignment decisions must use this value. config->maxPageSize = getMaxPageSize(args); - // CommonPageSize is the most common page size that the output will be run on. + // commonPageSize is the most common page size that the output will be run on. // For example if an OS can use 4k or 64k page sizes and 4k is more common - // than 64k then CommonPageSize is set to 4k. CommonPageSize can be used for + // than 64k then commonPageSize is set to 4k. commonPageSize can be used for // optimizations such as DATA_SEGMENT_ALIGN in linker scripts. LLD's use of it // is limited to writing trap instructions on the last executable segment. config->commonPageSize = getCommonPageSize(args); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 919012fd20ce9c..98b88283cf0930 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -229,7 +229,7 @@ static std::string getSrcMsgAux(ObjFile &file, const Symbol &sym, file.getVariableLoc(sym.getName())) return createFileLineMsg(fileLine->first, fileLine->second); - // File.SourceFile contains STT_FILE symbol, and that is a last resort. + // File.sourceFile contains STT_FILE symbol, and that is a last resort. return file.sourceFile; } @@ -269,7 +269,7 @@ template void ObjFile::initializeDwarf() { continue; lineTables.push_back(lt); - // Loop over variable records and insert them to VariableLoc. + // Loop over variable records and insert them to variableLoc. for (const auto &entry : cu->dies()) { DWARFDie die(cu.get(), &entry); // Skip all tags that are not variables. @@ -290,7 +290,7 @@ template void ObjFile::initializeDwarf() { // Get the line number on which the variable is declared. unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0); - // Here we want to take the variable name to add it into VariableLoc. + // Here we want to take the variable name to add it into variableLoc. // Variable can have regular and linkage name associated. At first, we try // to get linkage name as it can be different, for example when we have // two variables in different namespaces of the same object. Use common @@ -320,7 +320,7 @@ ObjFile::getVariableLoc(StringRef name) { // Take file name string from line table. std::string fileName; if (!it->second.lt->getFileNameByIndex( - it->second.file, nullptr, + it->second.file, {}, DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName)) return None; @@ -450,7 +450,7 @@ template ArrayRef ObjFile::getGlobalSymbols() { } template void ObjFile::parse(bool ignoreComdats) { - // Read a section table. JustSymbols is usually false. + // Read a section table. justSymbols is usually false. if (this->justSymbols) initializeJustSymbols(); else @@ -466,9 +466,11 @@ template void ObjFile::parse(bool ignoreComdats) { template StringRef ObjFile::getShtGroupSignature(ArrayRef sections, const Elf_Shdr &sec) { - const Elf_Sym *sym = - CHECK(object::getSymbol(this->getELFSyms(), sec.sh_info), this); - StringRef signature = CHECK(sym->getName(this->stringTable), this); + typename ELFT::SymRange symbols = this->getELFSyms(); + if (sec.sh_info >= symbols.size()) + fatal(toString(this) + ": invalid symbol index"); + const typename ELFT::Sym &sym = symbols[sec.sh_info]; + StringRef signature = CHECK(sym.getName(this->stringTable), this); // As a special case, if a symbol is a section symbol and has no name, // we use a section name as a signature. @@ -477,7 +479,7 @@ StringRef ObjFile::getShtGroupSignature(ArrayRef sections, // standard, but GNU gold 1.14 (the newest version as of July 2017) or // older produce such sections as outputs for the -r option, so we need // a bug-compatibility. - if (signature.empty() && sym->getType() == STT_SECTION) + if (signature.empty() && sym.getType() == STT_SECTION) return getSectionName(sec); return signature; } @@ -550,11 +552,11 @@ static void addDependentLibrary(StringRef specifier, const InputFile *f) { if (!config->dependentLibraries) return; if (fs::exists(specifier)) - driver->addFile(specifier, /*WithLOption=*/false); + driver->addFile(specifier, /*withLOption=*/false); else if (Optional s = findFromSearchPaths(specifier)) - driver->addFile(*s, /*WithLOption=*/true); + driver->addFile(*s, /*withLOption=*/true); else if (Optional s = searchLibraryBaseName(specifier)) - driver->addFile(*s, /*WithLOption=*/true); + driver->addFile(*s, /*withLOption=*/true); else error(toString(f) + ": unable to find library from dependent library specifier: " + @@ -1176,7 +1178,7 @@ static std::vector parseVerdefs(const uint8_t *base, // We cannot determine the largest verdef identifier without inspecting // every Elf_Verdef, but both bfd and gold assign verdef identifiers // sequentially starting from 1, so we predict that the largest identifier - // will be VerdefCount. + // will be verdefCount. unsigned verdefCount = sec->sh_info; std::vector verdefs(verdefCount + 1); @@ -1260,7 +1262,7 @@ template void SharedFile::parse() { return; } - // Search for a DT_SONAME tag to initialize this->SoName. + // Search for a DT_SONAME tag to initialize this->soName. for (const Elf_Dyn &dyn : dynamicTags) { if (dyn.d_tag == DT_NEEDED) { uint64_t val = dyn.getVal(); diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 760f72fd198a45..5ccc3d402b3761 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -117,7 +117,7 @@ class InputFile { // True if this is an argument for --just-symbols. Usually false. bool justSymbols = false; - // OutSecOff of .got2 in the current file. This is used by PPC32 -fPIC/-fPIE + // outSecOff of .got2 in the current file. This is used by PPC32 -fPIC/-fPIE // to compute offsets in PLT call stubs. uint32_t ppc32Got2OutSecOff = 0; @@ -132,7 +132,7 @@ class InputFile { // [.got, .got + 0xFFFC]. bool ppc64SmallCodeModelTocRelocs = false; - // GroupId is used for --warn-backrefs which is an optional error + // groupId is used for --warn-backrefs which is an optional error // checking feature. All files within the same --{start,end}-group or // --{start,end}-lib get the same group ID. Otherwise, each file gets a new // group ID. For more info, see checkDependency() in SymbolTable.cpp. diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 1ca520c3740efe..a024ac307b0a94 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -206,9 +206,9 @@ OutputSection *SectionBase::getOutputSection() { return sec ? sec->getParent() : nullptr; } -// When a section is compressed, `RawData` consists with a header followed +// When a section is compressed, `rawData` consists with a header followed // by zlib-compressed data. This function parses a header to initialize -// `UncompressedSize` member and remove the header from `RawData`. +// `uncompressedSize` member and remove the header from `rawData`. void InputSectionBase::parseCompressedHeader() { using Chdr64 = typename ELF64LE::Chdr; using Chdr32 = typename ELF32LE::Chdr; @@ -306,7 +306,7 @@ std::string InputSectionBase::getLocation(uint64_t offset) { return info->FileName + ":" + std::to_string(info->Line) + ":(" + secAndOffset + ")"; - // File->SourceFile contains STT_FILE symbol that contains a + // File->sourceFile contains STT_FILE symbol that contains a // source file name. If it's missing, we use an object file name. std::string srcFile = getFile()->sourceFile; if (srcFile.empty()) diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index dcd4848a0ab1e8..3a974074e0e51a 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -219,8 +219,8 @@ class InputSectionBase : public SectionBase { mutable ArrayRef rawData; - // This field stores the uncompressed size of the compressed data in RawData, - // or -1 if RawData is not compressed (either because the section wasn't + // This field stores the uncompressed size of the compressed data in rawData, + // or -1 if rawData is not compressed (either because the section wasn't // compressed in the first place, or because we ended up uncompressing it). // Since the feature is not used often, this is usually -1. mutable int64_t uncompressedSize = -1; diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp index 7230cc51044e4e..28d4bfe77c5d42 100644 --- a/lld/ELF/LTO.cpp +++ b/lld/ELF/LTO.cpp @@ -124,11 +124,11 @@ static lto::Config createConfig() { } BitcodeCompiler::BitcodeCompiler() { - // Initialize IndexFile. + // Initialize indexFile. if (!config->thinLTOIndexOnlyArg.empty()) indexFile = openFile(config->thinLTOIndexOnlyArg); - // Initialize LTOObj. + // Initialize ltoObj. lto::ThinBackend backend; if (config->thinLTOIndexOnly) { auto onIndexWrite = [&](StringRef s) { thinIndices.erase(s); }; @@ -142,7 +142,7 @@ BitcodeCompiler::BitcodeCompiler() { ltoObj = llvm::make_unique(createConfig(), backend, config->ltoPartitions); - // Initialize UsedStartStop. + // Initialize usedStartStop. symtab->forEachSymbol([&](Symbol *sym) { StringRef s = sym->getName(); for (StringRef prefix : {"__start_", "__stop_"}) diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index ce009149710fe7..49e44d7804761a 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -115,7 +115,7 @@ void LinkerScript::expandMemoryRegions(uint64_t size) { if (ctx->memRegion) expandMemoryRegion(ctx->memRegion, size, ctx->memRegion->name, ctx->outSec->name); - // Only expand the LMARegion if it is different from MemRegion. + // Only expand the LMARegion if it is different from memRegion. if (ctx->lmaRegion && ctx->memRegion != ctx->lmaRegion) expandMemoryRegion(ctx->lmaRegion, size, ctx->lmaRegion->name, ctx->outSec->name); @@ -1035,8 +1035,8 @@ static uint64_t getInitialDot() { return config->imageBase ? *config->imageBase : 0; uint64_t startAddr = UINT64_MAX; - // The Sections with -T
    have been sorted in order of ascending - // address. We must lower StartAddr if the lowest -T
    as + // The sections with -T
    have been sorted in order of ascending + // address. We must lower startAddr if the lowest -T
    as // calls to setDot() must be monotonically increasing. for (auto &kv : config->sectionStartMap) startAddr = std::min(startAddr, kv.second); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index d45d9aaad9af9b..3ebb46f2e1b2dc 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -416,6 +416,9 @@ defm wrap: Eq<"wrap", "Use wrapper functions for symbol">, def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"