diff --git a/.ci/generate-buildkite-pipeline-premerge b/.ci/generate-buildkite-pipeline-premerge index e1c66ac18e7ac0abb6b7dbeb29b29e22ed0642b6..bb7d2117e277fb433198d65aba611a7df3717ee3 100755 --- a/.ci/generate-buildkite-pipeline-premerge +++ b/.ci/generate-buildkite-pipeline-premerge @@ -53,7 +53,10 @@ echo "Directories modified:" >&2 echo "$modified_dirs" >&2 function compute-projects-to-test() { + isForWindows=$1 + shift projects=${@} + echo "isForWindows : $isForWindows ; projects: $projects " >&2 for project in ${projects}; do echo "${project}" case ${project} in @@ -63,9 +66,13 @@ function compute-projects-to-test() { done ;; llvm) - for p in bolt clang clang-tools-extra flang lld lldb mlir polly; do + for p in bolt clang clang-tools-extra lld lldb mlir polly; do echo $p done + # Flang is not stable in Windows CI at the moment + if [[ $isForWindows == 0 ]]; then + echo flang + fi ;; clang) for p in clang-tools-extra compiler-rt lldb cross-project-tests; do @@ -76,7 +83,26 @@ function compute-projects-to-test() { echo libc ;; mlir) - echo flang + # Flang is not stable in Windows CI at the moment + if [[ $isForWindows == 0 ]]; then + echo flang + fi + ;; + *) + # Nothing to do + ;; + esac + done +} + +function compute-runtimes-to-test() { + projects=${@} + for project in ${projects}; do + case ${project} in + clang) + for p in libcxx libcxxabi libunwind; do + echo $p + done ;; *) # Nothing to do @@ -178,6 +204,15 @@ function check-targets() { cross-project-tests) echo "check-cross-project" ;; + libcxx) + echo "check-cxx" + ;; + libcxxabi) + echo "check-cxxabi" + ;; + libunwind) + echo "check-unwind" + ;; lldb) echo "check-all" # TODO: check-lldb may not include all the LLDB tests? ;; @@ -207,17 +242,6 @@ if echo "$modified_dirs" | grep -q -E "^(libcxx|libcxxabi|libunwind|runtimes|cma EOF fi -# If clang changed. -if echo "$modified_dirs" | grep -q -E "^(clang)$"; then - cat < #include #include @@ -596,6 +597,9 @@ private: NameResolver NR; + // Regex object matching split function names. + const Regex ColdFragment{"(.*)\\.(cold|warm)(\\.[0-9]+)?"}; + friend class RewriteInstanceDiff; }; diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp index 0b44acb0816f2fab0c627ae7e451a7782732de53..e09b9ff92de06455dad9430ce460098b6bc550ae 100644 --- a/bolt/lib/Core/BinaryEmitter.cpp +++ b/bolt/lib/Core/BinaryEmitter.cpp @@ -485,6 +485,7 @@ void BinaryEmitter::emitFunctionBody(BinaryFunction &BF, FunctionFragment &FF, // This assumes the second instruction in the macro-op pair will get // assigned to its own MCRelaxableFragment. Since all JCC instructions // are relaxable, we should be safe. + Streamer.emitNeverAlignCodeAtEnd(/*Alignment to avoid=*/64, *BC.STI); } if (!EmitCodeOnly) { diff --git a/bolt/lib/Passes/ValidateMemRefs.cpp b/bolt/lib/Passes/ValidateMemRefs.cpp index f29a97c43f497c289edbadfef7a59461f90b9694..1d2c230fa7106a633c1992a8900aaa8080b8288b 100644 --- a/bolt/lib/Passes/ValidateMemRefs.cpp +++ b/bolt/lib/Passes/ValidateMemRefs.cpp @@ -29,8 +29,7 @@ bool ValidateMemRefs::checkAndFixJTReference(BinaryFunction &BF, MCInst &Inst, if (!BD) return false; - const uint64_t TargetAddress = BD->getAddress() + Offset; - JumpTable *JT = BC.getJumpTableContainingAddress(TargetAddress); + JumpTable *JT = BC.getJumpTableContainingAddress(BD->getAddress()); if (!JT) return false; @@ -41,10 +40,10 @@ bool ValidateMemRefs::checkAndFixJTReference(BinaryFunction &BF, MCInst &Inst, // Accessing a jump table in another function. This is not a // legitimate jump table access, we need to replace the reference to // the jump table label with a regular rodata reference. Get a - // non-JT reference by fetching the symbol 1 byte before the JT - // label. - MCSymbol *NewSym = BC.getOrCreateGlobalSymbol(TargetAddress - 1, "DATAat"); - BC.MIB->setOperandToSymbolRef(Inst, OperandNum, NewSym, 1, &*BC.Ctx, 0); + // non-JT reference by fetching the symbol 1 byte before the JT label. + MCSymbol *NewSym = BC.getOrCreateGlobalSymbol(BD->getAddress() - 1, "DATAat"); + BC.MIB->setOperandToSymbolRef(Inst, OperandNum, NewSym, Offset + 1, &*BC.Ctx, + 0); LLVM_DEBUG(dbgs() << "BOLT-DEBUG: replaced reference @" << BF.getPrintName() << " from " << BD->getName() << " to " << NewSym->getName() << " + 1\n"); diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 4b4913dd7a16c050afe4364cc71f51ca96555c4d..fb920ebbeafc4cd065954bc8f4e87a37f47bda9b 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -55,7 +55,6 @@ #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/Regex.h" #include "llvm/Support/Timer.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/raw_ostream.h" @@ -945,9 +944,6 @@ void RewriteInstance::discoverFileObjects() { BinaryFunction *PreviousFunction = nullptr; unsigned AnonymousId = 0; - // Regex object for matching cold fragments. - const Regex ColdFragment(".*\\.cold(\\.[0-9]+)?"); - const auto SortedSymbolsEnd = LastSymbol == SortedSymbols.end() ? LastSymbol : std::next(LastSymbol); for (auto Iter = SortedSymbols.begin(); Iter != SortedSymbolsEnd; ++Iter) { @@ -1460,10 +1456,10 @@ void RewriteInstance::registerFragments() { for (StringRef Name : Function.getNames()) { StringRef BaseName = NR.restore(Name); const bool IsGlobal = BaseName == Name; - const size_t ColdSuffixPos = BaseName.find(".cold"); - if (ColdSuffixPos == StringRef::npos) + SmallVector Matches; + if (!ColdFragment.match(BaseName, &Matches)) continue; - StringRef ParentName = BaseName.substr(0, ColdSuffixPos); + StringRef ParentName = Matches[1]; const BinaryData *BD = BC->getBinaryDataByName(ParentName); const uint64_t NumPossibleLocalParents = NR.getUniquifiedNameCount(ParentName); diff --git a/bolt/test/X86/register-fragments-bolt-symbols.s b/bolt/test/X86/register-fragments-bolt-symbols.s index 90c402b2234d761dd99c1883f76d22ba8435b38d..d4f39b7acf134c266330cb6ebc4a25a8b3939ddd 100644 --- a/bolt/test/X86/register-fragments-bolt-symbols.s +++ b/bolt/test/X86/register-fragments-bolt-symbols.s @@ -3,8 +3,20 @@ # RUN: llvm-mc --filetype=obj --triple x86_64-unknown-unknown %S/cdsplit-symbol-names.s -o %t.main.o # RUN: llvm-mc --filetype=obj --triple x86_64-unknown-unknown %s -o %t.chain.o # RUN: link_fdata %S/cdsplit-symbol-names.s %t.main.o %t.fdata -# RUN: sed -i 's|chain|chain/2|g' %t.fdata # RUN: llvm-strip --strip-unneeded %t.main.o + +## Check warm fragment name matching (produced by cdsplit) +# RUN: %clang %cflags %t.main.o -o %t.warm.exe -Wl,-q +# RUN: llvm-bolt %t.warm.exe -o %t.warm.bolt --split-functions --split-strategy=cdsplit \ +# RUN: --call-scale=2 --data=%t.fdata --reorder-blocks=ext-tsp --enable-bat +# RUN: link_fdata %s %t.warm.bolt %t.preagg.warm PREAGGWARM +# PREAGGWARM: B X:0 #chain.warm# 1 0 +# RUN: perf2bolt %t.warm.bolt -p %t.preagg.warm --pa -o %t.warm.fdata -w %t.warm.yaml \ +# RUN: -v=1 | FileCheck %s --check-prefix=CHECK-BOLT-WARM + +# CHECK-BOLT-WARM: marking chain.warm/1(*2) as a fragment of chain + +# RUN: sed -i 's|chain|chain/2|g' %t.fdata # RUN: llvm-objcopy --localize-symbol=chain %t.main.o # RUN: %clang %cflags %t.chain.o %t.main.o -o %t.exe -Wl,-q # RUN: llvm-bolt %t.exe -o %t.bolt --split-functions --split-strategy=randomN \ diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt index 05836719105269c6b3dd6e4f15add1c995c8734d..35e29b9a7d13670f2feb130aef1ef5cdef8d1119 100644 --- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt @@ -52,7 +52,6 @@ add_clang_library(clangTidyMiscModule genconfusable ClangDriverOptions ) -set_target_properties(clangTidyMiscModule PROPERTIES FOLDER "Clang Tools Extra/Libraries") clang_target_link_libraries(clangTidyMiscModule PRIVATE diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp index c3208392df1566f98b38933a71fe40d9cf26d976..828f13805a69802689cbe91d7af8a1c6a893ab5a 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -1414,13 +1414,21 @@ IdentifierNamingCheck::getDiagInfo(const NamingCheckId &ID, }}; } +StringRef IdentifierNamingCheck::getRealFileName(StringRef FileName) const { + auto Iter = RealFileNameCache.try_emplace(FileName); + SmallString<256U> &RealFileName = Iter.first->getValue(); + if (!Iter.second) + return RealFileName; + llvm::sys::fs::real_path(FileName, RealFileName); + return RealFileName; +} + const IdentifierNamingCheck::FileStyle & IdentifierNamingCheck::getStyleForFile(StringRef FileName) const { if (!GetConfigPerFile) return *MainFileStyle; - SmallString<128> RealFileName; - llvm::sys::fs::real_path(FileName, RealFileName); + StringRef RealFileName = getRealFileName(FileName); StringRef Parent = llvm::sys::path::parent_path(RealFileName); auto Iter = NamingStylesCache.find(Parent); if (Iter != NamingStylesCache.end()) diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h index 27c8e4bc768c40637147bff4d96ec4c1d44bf38c..646ec0eac8dd1c889dad7ad2dc932863cfbb363d 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h @@ -205,6 +205,7 @@ private: const NamingCheckFailure &Failure) const override; const FileStyle &getStyleForFile(StringRef FileName) const; + StringRef getRealFileName(StringRef FileName) const; /// Find the style kind of a field in an anonymous record. StyleKind findStyleKindForAnonField( @@ -222,6 +223,7 @@ private: /// Stores the style options as a vector, indexed by the specified \ref /// StyleKind, for a given directory. mutable llvm::StringMap NamingStylesCache; + mutable llvm::StringMap> RealFileNameCache; FileStyle *MainFileStyle; ClangTidyContext *Context; const bool GetConfigPerFile; diff --git a/clang-tools-extra/clangd/Config.h b/clang-tools-extra/clangd/Config.h index 4371c80a6c5877fc7a29777604e21413fb86dce0..41143b9ebc8d273f0bb287061655d3fc84615d23 100644 --- a/clang-tools-extra/clangd/Config.h +++ b/clang-tools-extra/clangd/Config.h @@ -110,10 +110,11 @@ struct Config { IncludesPolicy UnusedIncludes = IncludesPolicy::Strict; IncludesPolicy MissingIncludes = IncludesPolicy::None; - /// IncludeCleaner will not diagnose usages of these headers matched by - /// these regexes. struct { + /// IncludeCleaner will not diagnose usages of these headers matched by + /// these regexes. std::vector> IgnoreHeader; + bool AnalyzeAngledIncludes = false; } Includes; } Diagnostics; diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp b/clang-tools-extra/clangd/ConfigCompile.cpp index 5bb2eb4a9f803fb805244f87c139ac4cb4cdb2c5..f32f674443ffeb79e98304cdb46009c26a44a52b 100644 --- a/clang-tools-extra/clangd/ConfigCompile.cpp +++ b/clang-tools-extra/clangd/ConfigCompile.cpp @@ -572,32 +572,46 @@ struct FragmentCompiler { #else static llvm::Regex::RegexFlags Flags = llvm::Regex::NoFlags; #endif - auto Filters = std::make_shared>(); - for (auto &HeaderPattern : F.IgnoreHeader) { - // Anchor on the right. - std::string AnchoredPattern = "(" + *HeaderPattern + ")$"; - llvm::Regex CompiledRegex(AnchoredPattern, Flags); - std::string RegexError; - if (!CompiledRegex.isValid(RegexError)) { - diag(Warning, - llvm::formatv("Invalid regular expression '{0}': {1}", - *HeaderPattern, RegexError) - .str(), - HeaderPattern.Range); - continue; + std::shared_ptr> Filters; + if (!F.IgnoreHeader.empty()) { + Filters = std::make_shared>(); + for (auto &HeaderPattern : F.IgnoreHeader) { + // Anchor on the right. + std::string AnchoredPattern = "(" + *HeaderPattern + ")$"; + llvm::Regex CompiledRegex(AnchoredPattern, Flags); + std::string RegexError; + if (!CompiledRegex.isValid(RegexError)) { + diag(Warning, + llvm::formatv("Invalid regular expression '{0}': {1}", + *HeaderPattern, RegexError) + .str(), + HeaderPattern.Range); + continue; + } + Filters->push_back(std::move(CompiledRegex)); } - Filters->push_back(std::move(CompiledRegex)); } - if (Filters->empty()) + // Optional to override the resulting AnalyzeAngledIncludes + // only if it's explicitly set in the current fragment. + // Otherwise it's inherited from parent fragment. + std::optional AnalyzeAngledIncludes; + if (F.AnalyzeAngledIncludes.has_value()) + AnalyzeAngledIncludes = **F.AnalyzeAngledIncludes; + if (!Filters && !AnalyzeAngledIncludes.has_value()) return; - auto Filter = [Filters](llvm::StringRef Path) { - for (auto &Regex : *Filters) - if (Regex.match(Path)) - return true; - return false; - }; - Out.Apply.push_back([Filter](const Params &, Config &C) { - C.Diagnostics.Includes.IgnoreHeader.emplace_back(Filter); + Out.Apply.push_back([Filters = std::move(Filters), + AnalyzeAngledIncludes](const Params &, Config &C) { + if (Filters) { + auto Filter = [Filters](llvm::StringRef Path) { + for (auto &Regex : *Filters) + if (Regex.match(Path)) + return true; + return false; + }; + C.Diagnostics.Includes.IgnoreHeader.emplace_back(std::move(Filter)); + } + if (AnalyzeAngledIncludes.has_value()) + C.Diagnostics.Includes.AnalyzeAngledIncludes = *AnalyzeAngledIncludes; }); } diff --git a/clang-tools-extra/clangd/ConfigFragment.h b/clang-tools-extra/clangd/ConfigFragment.h index 7fa61108c78a05d10bb00f8a2b33375cf4cf5376..f3e51a9b6dbc4ba078fd6fbe944f016e738454ce 100644 --- a/clang-tools-extra/clangd/ConfigFragment.h +++ b/clang-tools-extra/clangd/ConfigFragment.h @@ -254,6 +254,10 @@ struct Fragment { /// unused or missing. These can match any suffix of the header file in /// question. std::vector> IgnoreHeader; + + /// If false (default), unused system headers will be ignored. + /// Standard library headers are analyzed regardless of this option. + std::optional> AnalyzeAngledIncludes; }; IncludesBlock Includes; diff --git a/clang-tools-extra/clangd/ConfigYAML.cpp b/clang-tools-extra/clangd/ConfigYAML.cpp index ce09af819247aecea89cb14a6ab67bf0f4d45c3a..3e9b6a07d3b325fb8ca19199c8f3556f273f596b 100644 --- a/clang-tools-extra/clangd/ConfigYAML.cpp +++ b/clang-tools-extra/clangd/ConfigYAML.cpp @@ -169,6 +169,10 @@ private: if (auto Values = scalarValues(N)) F.IgnoreHeader = std::move(*Values); }); + Dict.handle("AnalyzeAngledIncludes", [&](Node &N) { + if (auto Value = boolValue(N, "AnalyzeAngledIncludes")) + F.AnalyzeAngledIncludes = *Value; + }); Dict.parse(N); } diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp b/clang-tools-extra/clangd/IncludeCleaner.cpp index 8e48f546d94e7799ca727a5e3de0895c90fd69cd..01b47679790f1d52633b8bb8b49aeca13147a060 100644 --- a/clang-tools-extra/clangd/IncludeCleaner.cpp +++ b/clang-tools-extra/clangd/IncludeCleaner.cpp @@ -68,24 +68,30 @@ bool isIgnored(llvm::StringRef HeaderPath, HeaderFilter IgnoreHeaders) { } bool mayConsiderUnused(const Inclusion &Inc, ParsedAST &AST, - const include_cleaner::PragmaIncludes *PI) { + const include_cleaner::PragmaIncludes *PI, + bool AnalyzeAngledIncludes) { assert(Inc.HeaderID); auto HID = static_cast(*Inc.HeaderID); auto FE = AST.getSourceManager().getFileManager().getFileRef( AST.getIncludeStructure().getRealPath(HID)); assert(FE); if (FE->getDir() == AST.getPreprocessor() - .getHeaderSearchInfo() - .getModuleMap() - .getBuiltinDir()) + .getHeaderSearchInfo() + .getModuleMap() + .getBuiltinDir()) return false; if (PI && PI->shouldKeep(*FE)) return false; // FIXME(kirillbobyrev): We currently do not support the umbrella headers. // System headers are likely to be standard library headers. - // Until we have good support for umbrella headers, don't warn about them. - if (Inc.Written.front() == '<') - return tooling::stdlib::Header::named(Inc.Written).has_value(); + // Until we have good support for umbrella headers, don't warn about them + // (unless analysis is explicitly enabled). + if (Inc.Written.front() == '<') { + if (tooling::stdlib::Header::named(Inc.Written)) + return true; + if (!AnalyzeAngledIncludes) + return false; + } if (PI) { // Check if main file is the public interface for a private header. If so we // shouldn't diagnose it as unused. @@ -266,7 +272,8 @@ Fix fixAll(const Fix &RemoveAllUnused, const Fix &AddAllMissing) { std::vector getUnused(ParsedAST &AST, - const llvm::DenseSet &ReferencedFiles) { + const llvm::DenseSet &ReferencedFiles, + bool AnalyzeAngledIncludes) { trace::Span Tracer("IncludeCleaner::getUnused"); std::vector Unused; for (const Inclusion &MFI : AST.getIncludeStructure().MainFileIncludes) { @@ -275,7 +282,8 @@ getUnused(ParsedAST &AST, auto IncludeID = static_cast(*MFI.HeaderID); if (ReferencedFiles.contains(IncludeID)) continue; - if (!mayConsiderUnused(MFI, AST, &AST.getPragmaIncludes())) { + if (!mayConsiderUnused(MFI, AST, &AST.getPragmaIncludes(), + AnalyzeAngledIncludes)) { dlog("{0} was not used, but is not eligible to be diagnosed as unused", MFI.Written); continue; @@ -347,7 +355,8 @@ include_cleaner::Includes convertIncludes(const ParsedAST &AST) { return ConvertedIncludes; } -IncludeCleanerFindings computeIncludeCleanerFindings(ParsedAST &AST) { +IncludeCleanerFindings +computeIncludeCleanerFindings(ParsedAST &AST, bool AnalyzeAngledIncludes) { // Interaction is only polished for C/CPP. if (AST.getLangOpts().ObjC) return {}; @@ -432,7 +441,8 @@ IncludeCleanerFindings computeIncludeCleanerFindings(ParsedAST &AST) { MapInfo::getHashValue(RHS.Symbol); }); MissingIncludes.erase(llvm::unique(MissingIncludes), MissingIncludes.end()); - std::vector UnusedIncludes = getUnused(AST, Used); + std::vector UnusedIncludes = + getUnused(AST, Used, AnalyzeAngledIncludes); return {std::move(UnusedIncludes), std::move(MissingIncludes)}; } diff --git a/clang-tools-extra/clangd/IncludeCleaner.h b/clang-tools-extra/clangd/IncludeCleaner.h index 624e2116be7da3015816dfec628d8de6ac7f363c..a01146d14e3c17aacfd5b8798d3a46e5c737e362 100644 --- a/clang-tools-extra/clangd/IncludeCleaner.h +++ b/clang-tools-extra/clangd/IncludeCleaner.h @@ -53,7 +53,9 @@ struct IncludeCleanerFindings { std::vector MissingIncludes; }; -IncludeCleanerFindings computeIncludeCleanerFindings(ParsedAST &AST); +IncludeCleanerFindings +computeIncludeCleanerFindings(ParsedAST &AST, + bool AnalyzeAngledIncludes = false); using HeaderFilter = llvm::ArrayRef>; std::vector diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp index 3ff759415f7c8b24fab5a3a538c13755dd14544f..2bd1fbcad2ada0f69a269805e121f51ef144ced0 100644 --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -373,7 +373,8 @@ std::vector getIncludeCleanerDiags(ParsedAST &AST, llvm::StringRef Code, Cfg.Diagnostics.UnusedIncludes == Config::IncludesPolicy::None; if (SuppressMissing && SuppressUnused) return {}; - auto Findings = computeIncludeCleanerFindings(AST); + auto Findings = computeIncludeCleanerFindings( + AST, Cfg.Diagnostics.Includes.AnalyzeAngledIncludes); if (SuppressMissing) Findings.MissingIncludes.clear(); if (SuppressUnused) diff --git a/clang-tools-extra/clangd/unittests/ClangdTests.cpp b/clang-tools-extra/clangd/unittests/ClangdTests.cpp index 864337b98f44637b6a0e6a9126a022d5fe5727a5..c324643498d94cbb7c94da0521052e3f883515ee 100644 --- a/clang-tools-extra/clangd/unittests/ClangdTests.cpp +++ b/clang-tools-extra/clangd/unittests/ClangdTests.cpp @@ -392,7 +392,7 @@ TEST(ClangdServerTest, SearchLibDir) { ErrorCheckingCallbacks DiagConsumer; MockCompilationDatabase CDB; CDB.ExtraClangFlags.insert(CDB.ExtraClangFlags.end(), - {"-xc++", "-target", "x86_64-linux-unknown", + {"-xc++", "--target=x86_64-unknown-linux-gnu", "-m64", "--gcc-toolchain=/randomusr", "-stdlib=libstdc++"}); ClangdServer Server(CDB, FS, ClangdServer::optsForTest(), &DiagConsumer); diff --git a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp index f0ffc429c0ca9096621aa5700c191dcd01e666d6..4ecfdf0184ab40de2017ff9cb03f783706afa7d7 100644 --- a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp +++ b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp @@ -277,6 +277,12 @@ TEST_F(ConfigCompileTests, DiagnosticsIncludeCleaner) { }; EXPECT_TRUE(HeaderFilter("foo.h")); EXPECT_FALSE(HeaderFilter("bar.h")); + + Frag = {}; + EXPECT_FALSE(Conf.Diagnostics.Includes.AnalyzeAngledIncludes); + Frag.Diagnostics.Includes.AnalyzeAngledIncludes = true; + EXPECT_TRUE(compileAndApply()); + EXPECT_TRUE(Conf.Diagnostics.Includes.AnalyzeAngledIncludes); } TEST_F(ConfigCompileTests, DiagnosticSuppression) { diff --git a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp index 44a6647d4c0a818fe81541e555a51588866847b7..10d67dead342c3013ff8f6064ef6128c3d64c73a 100644 --- a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp +++ b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp @@ -278,6 +278,21 @@ Diagnostics: ElementsAre(val("foo"), val("bar"))); } +TEST(ParseYAML, IncludesAnalyzeAngledIncludes) { + CapturedDiags Diags; + Annotations YAML(R"yaml( +Diagnostics: + Includes: + AnalyzeAngledIncludes: true + )yaml"); + auto Results = + Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback()); + ASSERT_THAT(Diags.Diagnostics, IsEmpty()); + ASSERT_EQ(Results.size(), 1u); + EXPECT_THAT(Results[0].Diagnostics.Includes.AnalyzeAngledIncludes, + llvm::ValueIs(val(true))); +} + TEST(ParseYAML, Style) { CapturedDiags Diags; Annotations YAML(R"yaml( diff --git a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp index 142310837bd9ce276d92b6ab1f1e9bb4b20e35f2..7027232460354cd66982236edc04293d952528e3 100644 --- a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp +++ b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp @@ -108,6 +108,7 @@ TEST(IncludeCleaner, GetUnusedHeaders) { #include "unguarded.h" #include "unused.h" #include + #include void foo() { a(); b(); @@ -122,6 +123,7 @@ TEST(IncludeCleaner, GetUnusedHeaders) { TU.AdditionalFiles["dir/c.h"] = guard("void c();"); TU.AdditionalFiles["unused.h"] = guard("void unused();"); TU.AdditionalFiles["dir/unused.h"] = guard("void dirUnused();"); + TU.AdditionalFiles["dir/non_system_angled_header.h"] = guard(""); TU.AdditionalFiles["system/system_header.h"] = guard(""); TU.AdditionalFiles["unguarded.h"] = ""; TU.ExtraArgs.push_back("-I" + testPath("dir")); @@ -135,6 +137,48 @@ TEST(IncludeCleaner, GetUnusedHeaders) { Pointee(writtenInclusion("\"dir/unused.h\"")))); } +TEST(IncludeCleaner, IgnoredAngledHeaders) { + // Currently the default behavior is to ignore unused angled includes + auto TU = TestTU::withCode(R"cpp( + #include + #include + #include + SystemClass x; + )cpp"); + TU.AdditionalFiles["system/system_header.h"] = guard("class SystemClass {};"); + TU.AdditionalFiles["system/system_unused.h"] = guard(""); + TU.AdditionalFiles["dir/non_system_angled_unused.h"] = guard(""); + TU.ExtraArgs = { + "-isystem" + testPath("system"), + "-I" + testPath("dir"), + }; + auto AST = TU.build(); + IncludeCleanerFindings Findings = computeIncludeCleanerFindings(AST); + EXPECT_THAT(Findings.UnusedIncludes, IsEmpty()); +} + +TEST(IncludeCleaner, UnusedAngledHeaders) { + auto TU = TestTU::withCode(R"cpp( + #include + #include + #include + SystemClass x; + )cpp"); + TU.AdditionalFiles["system/system_header.h"] = guard("class SystemClass {};"); + TU.AdditionalFiles["system/system_unused.h"] = guard(""); + TU.AdditionalFiles["dir/non_system_angled_unused.h"] = guard(""); + TU.ExtraArgs = { + "-isystem" + testPath("system"), + "-I" + testPath("dir"), + }; + auto AST = TU.build(); + IncludeCleanerFindings Findings = computeIncludeCleanerFindings(AST, true); + EXPECT_THAT(Findings.UnusedIncludes, + UnorderedElementsAre( + Pointee(writtenInclusion("")), + Pointee(writtenInclusion("")))); +} + TEST(IncludeCleaner, ComputeMissingHeaders) { Annotations MainFile(R"cpp( #include "a.h" diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 3e3195f6f68139923a8c1931bb7090b17011a796..a5e87d26d96c383b00c4d9009c162c6fb3c88d75 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -84,6 +84,11 @@ Objective-C Miscellaneous ^^^^^^^^^^^^^ +- Added a boolean option `AnalyzeAngledIncludes` to `Includes` config section, + which allows to enable unused includes detection for all angled ("system") headers. + At this moment umbrella headers are not supported, so enabling this option + may result in false-positives. + Improvements to clang-doc ------------------------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-length.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-length.rst index 44d97f7b363bff6220bd761affabffe48054c89b..271970c292c8fab8fc939e5be2d117d7d366815c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-length.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-length.rst @@ -28,10 +28,7 @@ The following options are described below: .. code-block:: c++ - int doubler(int x) // warns that x is too short - { - return 2 * x; - } + int i = 42; // warns that 'i' is too short This check does not have any fix suggestions in the general case since variable names have semantic value. @@ -50,7 +47,10 @@ The following options are described below: .. code-block:: c++ - int i = 42; // warns that 'i' is too short + int doubler(int x) // warns that x is too short + { + return 2 * x; + } This check does not have any fix suggestions in the general case since variable names have semantic value. diff --git a/clang/cmake/caches/Fuchsia-stage2.cmake b/clang/cmake/caches/Fuchsia-stage2.cmake index 66e764968e85ce499f66668c63c564c9a7a673ff..d5546e20873b3c580684a5b1d330aeb0a462a944 100644 --- a/clang/cmake/caches/Fuchsia-stage2.cmake +++ b/clang/cmake/caches/Fuchsia-stage2.cmake @@ -19,6 +19,7 @@ set(LLVM_ENABLE_LLD ON CACHE BOOL "") set(LLVM_ENABLE_LTO ON CACHE BOOL "") set(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR ON CACHE BOOL "") set(LLVM_ENABLE_PLUGINS OFF CACHE BOOL "") +set(LLVM_ENABLE_TERMINFO OFF CACHE BOOL "") set(LLVM_ENABLE_UNWIND_TABLES OFF CACHE BOOL "") set(LLVM_ENABLE_Z3_SOLVER OFF CACHE BOOL "") set(LLVM_ENABLE_ZLIB ON CACHE BOOL "") diff --git a/clang/cmake/caches/Fuchsia.cmake b/clang/cmake/caches/Fuchsia.cmake index 4d3af3ad3f4031908415e2aad3ed56107e51f144..30a3b9116a461f3f65d2bfdfab0f5aaecccc2e6c 100644 --- a/clang/cmake/caches/Fuchsia.cmake +++ b/clang/cmake/caches/Fuchsia.cmake @@ -12,6 +12,7 @@ set(LLVM_ENABLE_DIA_SDK OFF CACHE BOOL "") set(LLVM_ENABLE_LIBEDIT OFF CACHE BOOL "") set(LLVM_ENABLE_LIBXML2 OFF CACHE BOOL "") set(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR ON CACHE BOOL "") +set(LLVM_ENABLE_TERMINFO OFF CACHE BOOL "") set(LLVM_ENABLE_UNWIND_TABLES OFF CACHE BOOL "") set(LLVM_ENABLE_Z3_SOLVER OFF CACHE BOOL "") set(LLVM_ENABLE_ZLIB OFF CACHE BOOL "") @@ -33,6 +34,7 @@ set(_FUCHSIA_BOOTSTRAP_PASSTHROUGH LibXml2_ROOT LLVM_ENABLE_CURL LLVM_ENABLE_HTTPLIB + LLVM_ENABLE_TERMINFO LLVM_ENABLE_LIBEDIT CURL_ROOT OpenSSL_ROOT @@ -45,6 +47,11 @@ set(_FUCHSIA_BOOTSTRAP_PASSTHROUGH CURSES_LIBRARIES PANEL_LIBRARIES + # Deprecated + Terminfo_ROOT + + Terminfo_LIBRARIES + # Deprecated LibEdit_ROOT diff --git a/clang/cmake/caches/VectorEngine.cmake b/clang/cmake/caches/VectorEngine.cmake index b429fb0997d7a0665a6d9f6fa5178fcaea2beae6..2f968a21cc407e7a79220b68cec30229101d22cf 100644 --- a/clang/cmake/caches/VectorEngine.cmake +++ b/clang/cmake/caches/VectorEngine.cmake @@ -13,7 +13,9 @@ # ninja # -# Disable ZLIB, and ZSTD for VE since there is no pre-compiled libraries. +# Disable TERMINFO, ZLIB, and ZSTD for VE since there is no pre-compiled +# libraries. +set(LLVM_ENABLE_TERMINFO OFF CACHE BOOL "") set(LLVM_ENABLE_ZLIB OFF CACHE BOOL "") set(LLVM_ENABLE_ZSTD OFF CACHE BOOL "") diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 6d092219877f91f68d46025cf550e37531f029d5..1a7d0e6a05e31348947368e765f953214a732915 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1421,13 +1421,21 @@ the configuration (without a prefix: ``Auto``). .. code-block:: c++ - true: #define A \ int aaaa; \ int b; \ int dddddddddd; - false: + * ``ENAS_LeftWithLastLine`` (in configuration: ``LeftWithLastLine``) + Align escaped newlines as far left as possible, using the last line of + the preprocessor directive as the reference if it's the longest. + + .. code-block:: c++ + + #define A \ + int aaaa; \ + int b; \ + int dddddddddd; * ``ENAS_Right`` (in configuration: ``Right``) Align escaped newlines in the right-most column. diff --git a/clang/docs/InternalsManual.rst b/clang/docs/InternalsManual.rst index b3e2b870ae5f9aad96983e3f6d678c999f7f3989..3d21e37784b36354d95d5dfccf34f5c0e7b74b8c 100644 --- a/clang/docs/InternalsManual.rst +++ b/clang/docs/InternalsManual.rst @@ -123,6 +123,44 @@ severe that error recovery won't be able to recover sensibly from them (thus spewing a ton of bogus errors). One example of this class of error are failure to ``#include`` a file. +Diagnostic Wording +^^^^^^^^^^^^^^^^^^ +The wording used for a diagnostic is critical because it is the only way for a +user to know how to correct their code. Use the following suggestions when +wording a diagnostic. + +* Diagnostics in Clang do not start with a capital letter and do not end with + punctuation. + + * This does not apply to proper nouns like ``Clang`` or ``OpenMP``, to + acronyms like ``GCC`` or ``ARC``, or to language standards like ``C23`` + or ``C++17``. + * A trailing question mark is allowed. e.g., ``unknown identifier %0; did + you mean %1?``. + +* Appropriately capitalize proper nouns like ``Clang``, ``OpenCL``, ``GCC``, + ``Objective-C``, etc and language standard versions like ``C11`` or ``C++11``. +* The wording should be succinct. If necessary, use a semicolon to combine + sentence fragments instead of using complete sentences. e.g., prefer wording + like ``'%0' is deprecated; it will be removed in a future release of Clang`` + over wording like ``'%0' is deprecated. It will be removed in a future release + of Clang``. +* The wording should be actionable and avoid using standards terms or grammar + productions that a new user would not be familiar with. e.g., prefer wording + like ``missing semicolon`` over wording like ``syntax error`` (which is not + actionable) or ``expected unqualified-id`` (which uses standards terminology). +* The wording should clearly explain what is wrong with the code rather than + restating what the code does. e.g., prefer wording like ``type %0 requires a + value in the range %1 to %2`` over wording like ``%0 is invalid``. +* The wording should have enough contextual information to help the user + identify the issue in a complex expression. e.g., prefer wording like + ``both sides of the %0 binary operator are identical`` over wording like + ``identical operands to binary operator``. +* Use single quotes to denote syntactic constructs or command line arguments + named in a diagnostic message. e.g., prefer wording like ``'this' pointer + cannot be null in well-defined C++ code`` over wording like ``this pointer + cannot be null in well-defined C++ code``. + The Format String ^^^^^^^^^^^^^^^^^ diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index a09c409f8f91a3da3b3a47ba15b846fd8103a5a6..46f99d0bbdd066932de0adbb7cb83ff5322ae36e 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -4403,6 +4403,7 @@ immediately after the name being declared. For example, this applies the GNU ``unused`` attribute to ``a`` and ``f``, and also applies the GNU ``noreturn`` attribute to ``f``. +Examples: .. code-block:: c++ [[gnu::unused]] int a, f [[gnu::noreturn]] (); @@ -4412,6 +4413,42 @@ Target-Specific Extensions Clang supports some language features conditionally on some targets. +AMDGPU Language Extensions +-------------------------- + +__builtin_amdgcn_fence +^^^^^^^^^^^^^^^^^^^^^^ + +``__builtin_amdgcn_fence`` emits a fence. + +* ``unsigned`` atomic ordering, e.g. ``__ATOMIC_ACQUIRE`` +* ``const char *`` synchronization scope, e.g. ``workgroup`` +* Zero or more ``const char *`` address spaces names. + +The address spaces arguments must be one of the following string literals: + +* ``"local"`` +* ``"global"`` + +If one or more address space name are provided, the code generator will attempt +to emit potentially faster instructions that order access to at least those +address spaces. +Emitting such instructions may not always be possible and the compiler is free +to fence more aggressively. + +If no address spaces names are provided, all address spaces are fenced. + +.. code-block:: c++ + + // Fence all address spaces. + __builtin_amdgcn_fence(__ATOMIC_SEQ_CST, "workgroup"); + __builtin_amdgcn_fence(__ATOMIC_ACQUIRE, "agent"); + + // Fence only requested address spaces. + __builtin_amdgcn_fence(__ATOMIC_SEQ_CST, "workgroup", "local") + __builtin_amdgcn_fence(__ATOMIC_SEQ_CST, "workgroup", "local", "global") + + ARM/AArch64 Language Extensions ------------------------------- @@ -5602,4 +5639,4 @@ Compiling different TUs depending on these flags (including use of ``std::hardware_constructive_interference`` or ``std::hardware_destructive_interference``) with different compilers, macro definitions, or architecture flags will lead to ODR violations and should be -avoided. \ No newline at end of file +avoided. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index d023f53754cb30e498eee47d3a54dd0a8ff8f620..44035f48cb3f97cc2e2bbf3e58f162382d1ced1d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -98,6 +98,8 @@ ABI Changes in This Version AST Dumping Potentially Breaking Changes ---------------------------------------- +- The text ast-dumper has improved printing of TemplateArguments. + Clang Frontend Potentially Breaking Changes ------------------------------------------- - Removed support for constructing on-stack ``TemplateArgumentList``\ s; interfaces should instead @@ -541,6 +543,9 @@ Improvements to Clang's diagnostics - Clang emits a ``-Wparentheses`` warning for expressions with consecutive comparisons like ``x < y < z``. Fixes #GH20456. +- Clang no longer emits a "declared here" note for a builtin function that has no declaration in source. + Fixes #GH93369. + Improvements to Clang's time-trace ---------------------------------- @@ -629,9 +634,14 @@ Bug Fixes in This Version - ``__is_array`` and ``__is_bounded_array`` no longer return ``true`` for zero-sized arrays. Fixes (#GH54705). +- Correctly reject declarations where a statement is required in C. + Fixes #GH92775 + Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- Fix crash when atomic builtins are called with pointer to zero-size struct (#GH90330) + Bug Fixes to Attribute Support ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -734,7 +744,6 @@ Bug Fixes to C++ Support from being explicitly specialized for a given implicit instantiation of the class template. - Fixed a crash when ``this`` is used in a dependent class scope function template specialization that instantiates to a static member function. - - Fix crash when inheriting from a cv-qualified type. Fixes #GH35603 - Fix a crash when the using enum declaration uses an anonymous enumeration. Fixes (#GH86790). - Handled an edge case in ``getFullyPackExpandedSize`` so that we now avoid a false-positive diagnostic. (#GH84220) @@ -794,12 +803,24 @@ Bug Fixes to C++ Support Fixes (#GH87210), (GH89541). - Clang no longer tries to check if an expression is immediate-escalating in an unevaluated context. Fixes (#GH91308). +- Fix a crash caused by a regression in the handling of ``source_location`` + in dependent contexts. Fixes (#GH92680). +- Fixed a crash when diagnosing failed conversions involving template parameter + packs. (#GH93076) +- Fixed a regression introduced in Clang 18 causing a static function overloading a non-static function + with the same parameters not to be diagnosed. (Fixes #GH93456). +- Clang now diagnoses unexpanded parameter packs in attributes. (Fixes #GH93269). +- Clang now allows ``@$``` in raw string literals. Fixes (#GH93130). +- Fix an assertion failure when checking invalid ``this`` usage in the wrong context. (Fixes #GH91536). +- Clang no longer models dependent NTTP arguments as ``TemplateParamObjectDecl`` s. Fixes (#GH84052). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ - Clang now properly preserves ``FoundDecls`` within a ``ConceptReference``. (#GH82628) - The presence of the ``typename`` keyword is now stored in ``TemplateTemplateParmDecl``. - Fixed malformed AST generated for anonymous union access in templates. (#GH90842) +- Improved preservation of qualifiers and sugar in `TemplateNames`, including + template keyword. Miscellaneous Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^ @@ -956,9 +977,10 @@ clang-format ``BreakTemplateDeclarations``. - ``AlwaysBreakAfterReturnType`` is deprecated and renamed to ``BreakAfterReturnType``. -- Handles Java ``switch`` expressions. +- Handles Java switch expressions. - Adds ``AllowShortCaseExpressionOnASingleLine`` option. - Adds ``AlignCaseArrows`` suboption to ``AlignConsecutiveShortCaseStatements``. +- Adds ``LeftWithLastLine`` suboption to ``AlignEscapedNewlines``. libclang -------- diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index ac9f0b06f63ba412da719ce605e24396f5c8ea9d..3a31708a1e9de6ce683b0dcb69d45f4efdcfefe8 100644 --- a/clang/docs/analyzer/checkers.rst +++ b/clang/docs/analyzer/checkers.rst @@ -2858,6 +2858,16 @@ The check corresponds to CERT rule return putenv(env); // putenv function should not be called with stack-allocated string } +There is one case where the checker can report a false positive. This is when +the stack-allocated array is used at `putenv` in a function or code branch that +does not return (calls `fork` or `exec` like function). + +Another special case is if the `putenv` is called from function `main`. Here +the stack is deallocated at the end of the program and it should be no problem +to use the stack-allocated string (a multi-threaded program may require more +attention). The checker does not warn for cases when stack space of `main` is +used at the `putenv` call. + .. _alpha-security-ReturnPtrRange: alpha.security.ReturnPtrRange (C) diff --git a/clang/include/clang/AST/StmtOpenACC.h b/clang/include/clang/AST/StmtOpenACC.h index b706864798baaf3f156aafcd1aafc848261f2944..04daf511f58713ce0b2be283ad3605f334c56352 100644 --- a/clang/include/clang/AST/StmtOpenACC.h +++ b/clang/include/clang/AST/StmtOpenACC.h @@ -31,6 +31,8 @@ class OpenACCConstructStmt : public Stmt { /// The location of the directive statement, from the '#' to the last token of /// the directive. SourceRange Range; + /// The location of the directive name. + SourceLocation DirectiveLoc; /// The list of clauses. This is stored here as an ArrayRef, as this is the /// most convienient place to access the list, however the list itself should @@ -39,8 +41,9 @@ class OpenACCConstructStmt : public Stmt { protected: OpenACCConstructStmt(StmtClass SC, OpenACCDirectiveKind K, - SourceLocation Start, SourceLocation End) - : Stmt(SC), Kind(K), Range(Start, End) {} + SourceLocation Start, SourceLocation DirectiveLoc, + SourceLocation End) + : Stmt(SC), Kind(K), Range(Start, End), DirectiveLoc(DirectiveLoc) {} // Used only for initialization, the leaf class can initialize this to // trailing storage. @@ -59,6 +62,7 @@ public: SourceLocation getBeginLoc() const { return Range.getBegin(); } SourceLocation getEndLoc() const { return Range.getEnd(); } + SourceLocation getDirectiveLoc() const { return DirectiveLoc; } ArrayRef clauses() const { return Clauses; } child_range children() { @@ -81,9 +85,11 @@ class OpenACCAssociatedStmtConstruct : public OpenACCConstructStmt { protected: OpenACCAssociatedStmtConstruct(StmtClass SC, OpenACCDirectiveKind K, - SourceLocation Start, SourceLocation End, - Stmt *AssocStmt) - : OpenACCConstructStmt(SC, K, Start, End), AssociatedStmt(AssocStmt) {} + SourceLocation Start, + SourceLocation DirectiveLoc, + SourceLocation End, Stmt *AssocStmt) + : OpenACCConstructStmt(SC, K, Start, DirectiveLoc, End), + AssociatedStmt(AssocStmt) {} void setAssociatedStmt(Stmt *S) { AssociatedStmt = S; } Stmt *getAssociatedStmt() { return AssociatedStmt; } @@ -126,10 +132,10 @@ class OpenACCComputeConstruct final friend class ASTStmtReader; friend class ASTContext; OpenACCComputeConstruct(unsigned NumClauses) - : OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, - OpenACCDirectiveKind::Invalid, - SourceLocation{}, SourceLocation{}, - /*AssociatedStmt=*/nullptr) { + : OpenACCAssociatedStmtConstruct( + OpenACCComputeConstructClass, OpenACCDirectiveKind::Invalid, + SourceLocation{}, SourceLocation{}, SourceLocation{}, + /*AssociatedStmt=*/nullptr) { // We cannot send the TrailingObjects storage to the base class (which holds // a reference to the data) until it is constructed, so we have to set it // separately here. @@ -141,11 +147,11 @@ class OpenACCComputeConstruct final } OpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation Start, - SourceLocation End, + SourceLocation DirectiveLoc, SourceLocation End, ArrayRef Clauses, Stmt *StructuredBlock) : OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, K, Start, - End, StructuredBlock) { + DirectiveLoc, End, StructuredBlock) { assert(isOpenACCComputeDirectiveKind(K) && "Only parallel, serial, and kernels constructs should be " "represented by this type"); @@ -169,8 +175,8 @@ public: unsigned NumClauses); static OpenACCComputeConstruct * Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc, - SourceLocation EndLoc, ArrayRef Clauses, - Stmt *StructuredBlock); + SourceLocation DirectiveLoc, SourceLocation EndLoc, + ArrayRef Clauses, Stmt *StructuredBlock); Stmt *getStructuredBlock() { return getAssociatedStmt(); } const Stmt *getStructuredBlock() const { diff --git a/clang/include/clang/AST/TemplateName.h b/clang/include/clang/AST/TemplateName.h index b7732e54ba1079f2d037e451f45bbe2e9dcec725..876be463c71d01a7a4db28038254c7c37c2b1a8c 100644 --- a/clang/include/clang/AST/TemplateName.h +++ b/clang/include/clang/AST/TemplateName.h @@ -332,7 +332,7 @@ public: /// unexpanded parameter pack (for C++0x variadic templates). bool containsUnexpandedParameterPack() const; - enum class Qualified { None, AsWritten, Fully }; + enum class Qualified { None, AsWritten }; /// Print the template name. /// /// \param OS the output stream to which the template name will be @@ -417,17 +417,18 @@ inline TemplateName TemplateName::getUnderlying() const { return *this; } -/// Represents a template name that was expressed as a -/// qualified name. +/// Represents a template name as written in source code. /// -/// This kind of template name refers to a template name that was +/// This kind of template name may refer to a template name that was /// preceded by a nested name specifier, e.g., \c std::vector. Here, /// the nested name specifier is "std::" and the template name is the -/// declaration for "vector". The QualifiedTemplateName class is only -/// used to provide "sugar" for template names that were expressed -/// with a qualified name, and has no semantic meaning. In this -/// manner, it is to TemplateName what ElaboratedType is to Type, -/// providing extra syntactic sugar for downstream clients. +/// declaration for "vector". It may also have been written with the +/// 'template' keyword. The QualifiedTemplateName class is only +/// used to provide "sugar" for template names, so that they can +/// be differentiated from canonical template names. and has no +/// semantic meaning. In this manner, it is to TemplateName what +/// ElaboratedType is to Type, providing extra syntactic sugar +/// for downstream clients. class QualifiedTemplateName : public llvm::FoldingSetNode { friend class ASTContext; diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index 1fede6e462e9253c253cc7cc302900084c2d48d6..63fa16c9ec47c1576a4a287a3dc29b235b52f9e1 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -213,6 +213,8 @@ public: void dumpTemplateSpecializationKind(TemplateSpecializationKind TSK); void dumpNestedNameSpecifier(const NestedNameSpecifier *NNS); void dumpConceptReference(const ConceptReference *R); + void dumpTemplateArgument(const TemplateArgument &TA); + void dumpTemplateName(TemplateName TN); void dumpDeclRef(const Decl *D, StringRef Label = {}); diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index e59cccccdd36907acc643120293d00e72273da03..ef9df1e9d8b4aaae8d9e5777a93571624b8ae926 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2025,9 +2025,12 @@ def Convergent : InheritableAttr { def NoInline : DeclOrStmtAttr { let Spellings = [CustomKeyword<"__noinline__">, GCC<"noinline">, CXX11<"clang", "noinline">, C23<"clang", "noinline">, + CXX11<"msvc", "noinline">, C23<"msvc", "noinline">, Declspec<"noinline">]; - let Accessors = [Accessor<"isClangNoInline", [CXX11<"clang", "noinline">, - C23<"clang", "noinline">]>]; + let Accessors = [Accessor<"isStmtNoInline", [CXX11<"clang", "noinline">, + C23<"clang", "noinline">, + CXX11<"msvc", "noinline">, + C23<"msvc", "noinline">]>]; let Documentation = [NoInlineDocs]; let Subjects = SubjectList<[Function, Stmt], WarnDiag, "functions and statements">; diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def index efa652eee990150cb0a6cce45b16a0ba0931d1a7..433c7795325f0c75c7418be4b9df8273bed172f3 100644 --- a/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -68,7 +68,7 @@ BUILTIN(__builtin_amdgcn_sched_group_barrier, "vIiIiIi", "n") BUILTIN(__builtin_amdgcn_iglp_opt, "vIi", "n") BUILTIN(__builtin_amdgcn_s_dcache_inv, "v", "n") BUILTIN(__builtin_amdgcn_buffer_wbinvl1, "v", "n") -BUILTIN(__builtin_amdgcn_fence, "vUicC*", "n") +BUILTIN(__builtin_amdgcn_fence, "vUicC*.", "n") BUILTIN(__builtin_amdgcn_groupstaticsize, "Ui", "n") BUILTIN(__builtin_amdgcn_wavefrontsize, "Ui", "nc") diff --git a/clang/include/clang/Basic/BuiltinsWebAssembly.def b/clang/include/clang/Basic/BuiltinsWebAssembly.def index fd8c1b480d6da0f9d763ce35f987c82dc21b7cd2..4e48ff48b60f5f0e9fc9f4176b62680af1fa7bb1 100644 --- a/clang/include/clang/Basic/BuiltinsWebAssembly.def +++ b/clang/include/clang/Basic/BuiltinsWebAssembly.def @@ -135,6 +135,10 @@ TARGET_BUILTIN(__builtin_wasm_min_f64x2, "V2dV2dV2d", "nc", "simd128") TARGET_BUILTIN(__builtin_wasm_max_f64x2, "V2dV2dV2d", "nc", "simd128") TARGET_BUILTIN(__builtin_wasm_pmin_f64x2, "V2dV2dV2d", "nc", "simd128") TARGET_BUILTIN(__builtin_wasm_pmax_f64x2, "V2dV2dV2d", "nc", "simd128") +TARGET_BUILTIN(__builtin_wasm_min_f16x8, "V8hV8hV8h", "nc", "half-precision") +TARGET_BUILTIN(__builtin_wasm_max_f16x8, "V8hV8hV8h", "nc", "half-precision") +TARGET_BUILTIN(__builtin_wasm_pmin_f16x8, "V8hV8hV8h", "nc", "half-precision") +TARGET_BUILTIN(__builtin_wasm_pmax_f16x8, "V8hV8hV8h", "nc", "half-precision") TARGET_BUILTIN(__builtin_wasm_ceil_f32x4, "V4fV4f", "nc", "simd128") TARGET_BUILTIN(__builtin_wasm_floor_f32x4, "V4fV4f", "nc", "simd128") diff --git a/clang/include/clang/Basic/CharInfo.h b/clang/include/clang/Basic/CharInfo.h index d80795531182871cef191348cac17b3978b789e7..d71857e8e5dcc3911922eaadbc1d440d1c13266c 100644 --- a/clang/include/clang/Basic/CharInfo.h +++ b/clang/include/clang/Basic/CharInfo.h @@ -28,8 +28,7 @@ namespace charinfo { CHAR_LOWER = 0x0040, // a-z CHAR_UNDER = 0x0080, // _ CHAR_PERIOD = 0x0100, // . - CHAR_RAWDEL = 0x0200, // {}[]#<>%:;?*+-/^&|~!=,"' - CHAR_PUNCT = 0x0400 // `$@() + CHAR_PUNCT = 0x0200, // {}[]#<>%:;?*+-/^&|~!=,"'`$@() }; enum { @@ -152,7 +151,7 @@ LLVM_READONLY inline bool isHexDigit(unsigned char c) { /// Note that '_' is both a punctuation character and an identifier character! LLVM_READONLY inline bool isPunctuation(unsigned char c) { using namespace charinfo; - return (InfoTable[c] & (CHAR_UNDER|CHAR_PERIOD|CHAR_RAWDEL|CHAR_PUNCT)) != 0; + return (InfoTable[c] & (CHAR_UNDER | CHAR_PERIOD | CHAR_PUNCT)) != 0; } /// Return true if this character is an ASCII printable character; that is, a @@ -160,8 +159,8 @@ LLVM_READONLY inline bool isPunctuation(unsigned char c) { /// terminal. LLVM_READONLY inline bool isPrintable(unsigned char c) { using namespace charinfo; - return (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_PERIOD|CHAR_PUNCT| - CHAR_DIGIT|CHAR_UNDER|CHAR_RAWDEL|CHAR_SPACE)) != 0; + return (InfoTable[c] & (CHAR_UPPER | CHAR_LOWER | CHAR_PERIOD | CHAR_PUNCT | + CHAR_DIGIT | CHAR_UNDER | CHAR_SPACE)) != 0; } /// Return true if this is the body character of a C preprocessing number, @@ -175,8 +174,9 @@ LLVM_READONLY inline bool isPreprocessingNumberBody(unsigned char c) { /// Return true if this is the body character of a C++ raw string delimiter. LLVM_READONLY inline bool isRawStringDelimBody(unsigned char c) { using namespace charinfo; - return (InfoTable[c] & (CHAR_UPPER|CHAR_LOWER|CHAR_PERIOD| - CHAR_DIGIT|CHAR_UNDER|CHAR_RAWDEL)) != 0; + return (InfoTable[c] & (CHAR_UPPER | CHAR_LOWER | CHAR_PERIOD | CHAR_DIGIT | + CHAR_UNDER | CHAR_PUNCT)) != 0 && + c != '(' && c != ')'; } enum class EscapeChar { diff --git a/clang/include/clang/Basic/DebugOptions.def b/clang/include/clang/Basic/DebugOptions.def index b94f6aef9ac60bf142d00a6be0c5c533107a80c9..bc96d5dfdf890bef53dfd79ec907bdf9e7b8197f 100644 --- a/clang/include/clang/Basic/DebugOptions.def +++ b/clang/include/clang/Basic/DebugOptions.def @@ -68,6 +68,8 @@ BENIGN_DEBUGOPT(NoInlineLineTables, 1, 0) ///< Whether debug info should contain ///< inline line tables. DEBUGOPT(DebugStrictDwarf, 1, 1) ///< Whether or not to use strict DWARF info. +DEBUGOPT(DebugOmitUnreferencedMethods, 1, 0) ///< Omit unreferenced member + ///< functions in type debug info. /// Control the Assignment Tracking debug info feature. BENIGN_ENUM_DEBUGOPT(AssignmentTrackingMode, AssignmentTrackingOpts, 2, diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index 5a4551a96ca4e782343258875e3029ca2c02430c..25fbfe83fa2bcf9b3491fa4af38f0d6612a40ed9 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -111,6 +111,14 @@ def warn_cxx98_compat_raw_string_literal : Warning< "raw string literals are incompatible with C++98">, InGroup, DefaultIgnore; +def warn_cxx26_compat_raw_string_literal_character_set : Warning< + " '%0' in a raw string literal delimiter is incompatible " + "with standards before C++2c">, + InGroup, DefaultIgnore; +def ext_cxx26_raw_string_literal_character_set : Extension< + " '%0' in a raw string literal delimiter is a C++2c extension">, + InGroup, DefaultIgnore; + def warn_multichar_character_literal : Warning< "multi-character character constant">, InGroup; def warn_four_char_character_literal : Warning< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 270b0a1e01307988565a36031eb30248ca67176e..f15cba63624ea6bb394403ae04f7842421604062 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -855,7 +855,7 @@ def note_strncat_wrong_size : Note< "the terminating null byte">; def warn_assume_side_effects : Warning< - "the argument to %0 has side effects that will be discarded">, + "assumption is ignored because it contains (potential) side-effects">, InGroup>; def warn_omp_assume_attribute_string_unknown : Warning< "unknown assumption string '%0'; attribute is potentially ignored">, @@ -8860,8 +8860,10 @@ def err_builtin_fn_use : Error<"builtin functions must be directly called">; def warn_call_wrong_number_of_arguments : Warning< "too %select{few|many}0 arguments in call to %1">; + def err_atomic_builtin_must_be_pointer : Error< - "address argument to atomic builtin must be a pointer (%0 invalid)">; + "address argument to atomic builtin must be a pointer %select{|to a non-zero-sized object }1(%0 invalid)">; + def err_atomic_builtin_must_be_pointer_intptr : Error< "address argument to atomic builtin must be a pointer to integer or pointer" " (%0 invalid)">; diff --git a/clang/include/clang/Basic/arm_sme.td b/clang/include/clang/Basic/arm_sme.td index 80e635e4a57eca78ac1413ced1d49f5a5da7a22a..564a58e4eb6709eafad66e54da6ea502e9f7c3be 100644 --- a/clang/include/clang/Basic/arm_sme.td +++ b/clang/include/clang/Basic/arm_sme.td @@ -146,6 +146,25 @@ let TargetGuard = "sme" in { [IsOverloadNone, IsStreamingCompatible, IsOutZA]>; } +let TargetGuard = "sme2p1" in { + def SVZERO_ZA64_VG1x2 : SInst<"svzero_za64_vg1x2", "vm", "", MergeNone, "aarch64_sme_zero_za64_vg1x2", + [IsOverloadNone, IsStreaming, IsInOutZA]>; + def SVZERO_ZA64_VG1x4 : SInst<"svzero_za64_vg1x4", "vm", "", MergeNone, "aarch64_sme_zero_za64_vg1x4", + [IsOverloadNone, IsStreaming, IsInOutZA]>; + def SVZERO_ZA64_VG2x1 : SInst<"svzero_za64_vg2x1", "vm", "", MergeNone, "aarch64_sme_zero_za64_vg2x1", + [IsOverloadNone, IsStreaming, IsInOutZA]>; + def SVZERO_ZA64_VG2x2 : SInst<"svzero_za64_vg2x2", "vm", "", MergeNone, "aarch64_sme_zero_za64_vg2x2", + [IsOverloadNone, IsStreaming, IsInOutZA]>; + def SVZERO_ZA64_VG2x4 : SInst<"svzero_za64_vg2x4", "vm", "", MergeNone, "aarch64_sme_zero_za64_vg2x4", + [IsOverloadNone, IsStreaming, IsInOutZA]>; + def SVZERO_ZA64_VG4x1 : SInst<"svzero_za64_vg4x1", "vm", "", MergeNone, "aarch64_sme_zero_za64_vg4x1", + [IsOverloadNone, IsStreaming, IsInOutZA]>; + def SVZERO_ZA64_VG4x2 : SInst<"svzero_za64_vg4x2", "vm", "", MergeNone, "aarch64_sme_zero_za64_vg4x2", + [IsOverloadNone, IsStreaming, IsInOutZA]>; + def SVZERO_ZA64_VG4x4 : SInst<"svzero_za64_vg4x4", "vm", "", MergeNone, "aarch64_sme_zero_za64_vg4x4", + [IsOverloadNone, IsStreaming, IsInOutZA]>; +} + //////////////////////////////////////////////////////////////////////////////// // SME - Counting elements in a streaming vector diff --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td index 03570f94de66663f0403c25465010159008ca5b2..88938a981fd8ae12a3ad47cdd7d5d43cce5bd8f2 100644 --- a/clang/include/clang/Basic/arm_sve.td +++ b/clang/include/clang/Basic/arm_sve.td @@ -2151,6 +2151,11 @@ let TargetGuard = "sme2" in { def SVFCLAMP_X4 : SInst<"svclamp[_single_{d}_x4]", "44dd", "hfd", MergeNone, "aarch64_sve_fclamp_single_x4", [IsStreaming], []>; } +let TargetGuard = "sme2,b16b16"in { + def SVBFCLAMP_X2 : SInst<"svclamp[_single_{d}_x2]", "22dd", "b", MergeNone, "aarch64_sve_bfclamp_single_x2", [IsStreaming], []>; + def SVBFCLAMP_X4 : SInst<"svclamp[_single_{d}_x4]", "44dd", "b", MergeNone, "aarch64_sve_bfclamp_single_x4", [IsStreaming], []>; +} + let TargetGuard = "sme2" in { // == ADD (vectors) == def SVADD_SINGLE_X2 : SInst<"svadd[_single_{d}_x2]", "22d", "cUcsUsiUilUl", MergeNone, "aarch64_sve_add_single_x2", [IsStreaming], []>; @@ -2265,6 +2270,10 @@ let TargetGuard = "sme2" in { def SVCVT_S32_F32_X4 : SInst<"svcvt_{d}[_f32_x4]", "4.d4.M", "i", MergeNone, "aarch64_sve_fcvtzs_x4", [IsStreaming, IsOverloadWhileOrMultiVecCvt], []>; } +let TargetGuard = "sme-f16f16" in { + def SVCVT_F32_X2 : SInst<"svcvt_{d}[_f16_x2]", "2h", "f", MergeNone, "aarch64_sve_fcvt_widen_x2", [ IsStreaming],[]>; +} + // // Multi-vector floating-point convert from single-precision to interleaved half-precision/BFloat16 // @@ -2273,6 +2282,13 @@ let TargetGuard = "sme2" in { def SVCVTN_BF16_X2 : SInst<"svcvtn_bf16[_f32_x2]", "$2", "f", MergeNone, "aarch64_sve_bfcvtn_x2", [IsOverloadNone, IsStreaming],[]>; } +// +//Multi-vector floating-point convert from half-precision to deinterleaved single-precision. +// +let TargetGuard = "sme-f16f16" in { + def SVCVTL_F32_X2 : SInst<"svcvtl_f32[_f16_x2]", "2h", "f", MergeNone, "aarch64_sve_fcvtl_widen_x2", [ IsStreaming],[]>; +} + // // Multi-vector saturating extract narrow // diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index de2f245fb29f8e20c2fd1bc2cd9fda7d4cb54cb8..da24e2b4a33d0b3573458c3132507e6fc8ba03a8 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4345,6 +4345,10 @@ defm strict_dwarf : BoolOption<"g", "strict-dwarf", "the specified version, avoiding features from later versions.">, NegFlag, BothFlags<[], [ClangOption, CLOption, DXCOption]>>, Group; +defm omit_unreferenced_methods : BoolGOption<"omit-unreferenced-methods", + CodeGenOpts<"DebugOmitUnreferencedMethods">, DefaultFalse, + NegFlag, + PosFlag, BothFlags<[], [ClangOption, CLOption, DXCOption]>>; defm column_info : BoolOption<"g", "column-info", CodeGenOpts<"DebugColumnInfo">, DefaultTrue, NegFlag, @@ -5461,6 +5465,10 @@ def pg : Flag<["-"], "pg">, HelpText<"Enable mcount instrumentation">, MarshallingInfoFlag>; def pipe : Flag<["-", "--"], "pipe">, HelpText<"Use pipes between commands, when possible">; +// Facebook T92898286 +def post_link_optimize : Flag<["--"], "post-link-optimize">, + HelpText<"Apply post-link optimizations using BOLT">; +// End Facebook T92898286 def prebind__all__twolevel__modules : Flag<["-"], "prebind_all_twolevel_modules">; def prebind : Flag<["-"], "prebind">; def preload : Flag<["-"], "preload">; @@ -6277,11 +6285,9 @@ def mapx_features_EQ : CommaJoined<["-"], "mapx-features=">, Group, Values<"egpr,push2pop2,ppx,ndd,ccmp,nf,cf">; def mno_apx_features_EQ : CommaJoined<["-"], "mno-apx-features=">, Group, HelpText<"Disable features of APX">, Values<"egpr,push2pop2,ppx,ndd,ccmp,nf,cf">; -// Features egpr, push2pop2, ppx and ndd are validated with llvm-test-suite && cpu2017 on Intel SDE. -// For stability, we turn on these features only for -mapxf. After a feature pass the validation, -// we will add it to -mapxf. -def mapxf : Flag<["-"], "mapxf">, Alias, AliasArgs<["egpr","push2pop2","ppx", "ndd"]>; -def mno_apxf : Flag<["-"], "mno-apxf">, Alias, AliasArgs<["egpr","push2pop2","ppx","ndd"]>; +// For stability, we only add a feature to -mapxf after it passes the validation of llvm-test-suite && cpu2017 on Intel SDE. +def mapxf : Flag<["-"], "mapxf">, Alias, AliasArgs<["egpr","push2pop2","ppx","ndd","ccmp","nf"]>; +def mno_apxf : Flag<["-"], "mno-apxf">, Alias, AliasArgs<["egpr","push2pop2","ppx","ndd","ccmp","nf"]>; } // let Flags = [TargetSpecific] // VE feature flags diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h index 8ccebe457ed530c486c7e78f0b0c29fd5fadd602..76d7fd798bed3a632b0d9045e2ad6d18516763b5 100644 --- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -21,6 +21,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ParentMapContext.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" @@ -127,7 +128,7 @@ public: protected: /// Collect API information for the enum constants and associate with the /// parent enum. - void recordEnumConstants(EnumRecord *EnumRecord, + void recordEnumConstants(SymbolReference Container, const EnumDecl::enumerator_range Constants); /// Collect API information for the Objective-C methods and associate with the @@ -248,12 +249,8 @@ protected: clang::index::generateUSRForDecl(Tag, TagUSR); if (auto *Record = llvm::dyn_cast_if_present( API.findRecordForUSR(TagUSR))) { - if (Record->IsEmbeddedInVarDeclarator) { + if (Record->IsEmbeddedInVarDeclarator) NewRecordContext->stealRecordChain(*Record); - auto *NewRecord = cast(NewRecordContext); - if (NewRecord->Comment.empty()) - NewRecord->Comment = Record->Comment; - } } } }; @@ -394,17 +391,6 @@ bool ExtractAPIVisitorBase::VisitEnumDecl(const EnumDecl *Decl) { if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) return true; - SmallString<128> QualifiedNameBuffer; - // Collect symbol information. - StringRef Name = Decl->getName(); - if (Name.empty()) - Name = getTypedefName(Decl); - if (Name.empty()) { - llvm::raw_svector_ostream OS(QualifiedNameBuffer); - Decl->printQualifiedName(OS); - Name = QualifiedNameBuffer; - } - SmallString<128> USR; index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = @@ -420,13 +406,29 @@ bool ExtractAPIVisitorBase::VisitEnumDecl(const EnumDecl *Decl) { DeclarationFragmentsBuilder::getFragmentsForEnum(Decl); DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - auto *ER = API.createRecord( - USR, Name, createHierarchyInformationForDecl(*Decl), Loc, - AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, - isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl)); + + // Collect symbol information. + SymbolReference ParentContainer; + + if (Decl->hasNameForLinkage()) { + StringRef Name = Decl->getName(); + if (Name.empty()) + Name = getTypedefName(Decl); + + auto *ER = API.createRecord( + USR, Name, createHierarchyInformationForDecl(*Decl), Loc, + AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, + SubHeading, isInSystemHeader(Decl), false); + ParentContainer = SymbolReference(ER); + } else { + // If this an anonymous enum then the parent scope of the constants is the + // top level namespace. + ParentContainer = {}; + } // Now collect information about the enumerators in this enum. - getDerivedExtractAPIVisitor().recordEnumConstants(ER, Decl->enumerators()); + getDerivedExtractAPIVisitor().recordEnumConstants(ParentContainer, + Decl->enumerators()); return true; } @@ -1197,7 +1199,7 @@ bool ExtractAPIVisitorBase::VisitObjCCategoryDecl( /// parent enum. template void ExtractAPIVisitorBase::recordEnumConstants( - EnumRecord *EnumRecord, const EnumDecl::enumerator_range Constants) { + SymbolReference Container, const EnumDecl::enumerator_range Constants) { for (const auto *Constant : Constants) { // Collect symbol information. StringRef Name = Constant->getName(); @@ -1218,9 +1220,8 @@ void ExtractAPIVisitorBase::recordEnumConstants( DeclarationFragmentsBuilder::getSubHeading(Constant); API.createRecord( - USR, Name, createHierarchyInformationForDecl(*Constant), Loc, - AvailabilityInfo::createFromDecl(Constant), Comment, Declaration, - SubHeading, isInSystemHeader(Constant)); + USR, Name, Container, Loc, AvailabilityInfo::createFromDecl(Constant), + Comment, Declaration, SubHeading, isInSystemHeader(Constant)); } } @@ -1469,7 +1470,17 @@ public: bool shouldDeclBeIncluded(const Decl *D) const { return true; } const RawComment *fetchRawCommentForDecl(const Decl *D) const { - return this->Context.getRawCommentForDeclNoCache(D); + if (const auto *Comment = this->Context.getRawCommentForDeclNoCache(D)) + return Comment; + + if (const auto *Declarator = dyn_cast(D)) { + const auto *TagTypeDecl = Declarator->getType()->getAsTagDecl(); + if (TagTypeDecl && TagTypeDecl->isEmbeddedInDeclarator() && + TagTypeDecl->isCompleteDefinition()) + return this->Context.getRawCommentForDeclNoCache(TagTypeDecl); + } + + return nullptr; } }; diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 274b45d1bc586555cf037024023b50d0188c68e1..eb6647038403d639575f5fd4f3c4bd4dfbcdd64b 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -480,15 +480,21 @@ struct FormatStyle { ENAS_DontAlign, /// Align escaped newlines as far left as possible. /// \code - /// true: /// #define A \ /// int aaaa; \ /// int b; \ /// int dddddddddd; - /// - /// false: /// \endcode ENAS_Left, + /// Align escaped newlines as far left as possible, using the last line of + /// the preprocessor directive as the reference if it's the longest. + /// \code + /// #define A \ + /// int aaaa; \ + /// int b; \ + /// int dddddddddd; + /// \endcode + ENAS_LeftWithLastLine, /// Align escaped newlines in the right-most column. /// \code /// #define A \ diff --git a/clang/include/clang/Interpreter/Interpreter.h b/clang/include/clang/Interpreter/Interpreter.h index 970e0245417b5198b03b32f5ba4ee20ffe218128..1234608bb58647148f4d37006e408919b4c63c0d 100644 --- a/clang/include/clang/Interpreter/Interpreter.h +++ b/clang/include/clang/Interpreter/Interpreter.h @@ -110,9 +110,9 @@ class Interpreter { RuntimeInterfaceBuilder::TransformExprFunction *AddPrintValueCall = nullptr; protected: - // Derived classes can make use an extended interface of the Interpreter. - // That's useful for testing and out-of-tree clients. - Interpreter(std::unique_ptr CI, llvm::Error &Err); + // Derived classes can use an extended interface of the Interpreter. + Interpreter(std::unique_ptr CI, llvm::Error &Err, + std::unique_ptr JITBuilder = nullptr); // Create the internal IncrementalExecutor, or re-create it after calling // ResetExecutor(). @@ -128,13 +128,6 @@ protected: // custom runtime. virtual std::unique_ptr FindRuntimeInterface(); - // Lazily construct thev ORCv2 JITBuilder. This called when the internal - // IncrementalExecutor is created. The default implementation populates an - // in-process JIT with debugging support. Override this to configure the JIT - // engine used for execution. - virtual llvm::Expected> - CreateJITBuilder(CompilerInstance &CI); - public: virtual ~Interpreter(); @@ -189,6 +182,8 @@ private: llvm::DenseMap Dtors; llvm::SmallVector ValuePrintingInfo; + + std::unique_ptr JITBuilder; }; } // namespace clang diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 8493026f5f7a69290b8d2f41d012771c36eee79f..d054b8cf0d24057079bae53619d5dc7d8940328a 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -467,15 +467,18 @@ class Parser : public CodeCompletionHandler { /// Flags describing a context in which we're parsing a statement. enum class ParsedStmtContext { + /// This context permits declarations in language modes where declarations + /// are not statements. + AllowDeclarationsInC = 0x1, /// This context permits standalone OpenMP directives. - AllowStandaloneOpenMPDirectives = 0x1, + AllowStandaloneOpenMPDirectives = 0x2, /// This context is at the top level of a GNU statement expression. - InStmtExpr = 0x2, + InStmtExpr = 0x4, /// The context of a regular substatement. SubStmt = 0, /// The context of a compound-statement. - Compound = AllowStandaloneOpenMPDirectives, + Compound = AllowDeclarationsInC | AllowStandaloneOpenMPDirectives, LLVM_MARK_AS_BITMASK_ENUM(InStmtExpr) }; @@ -3656,6 +3659,7 @@ private: struct OpenACCDirectiveParseInfo { OpenACCDirectiveKind DirKind; SourceLocation StartLoc; + SourceLocation DirLoc; SourceLocation EndLoc; SmallVector Clauses; // TODO OpenACC: As we implement support for the Atomic, Routine, Cache, and diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 52473791818086bddaf9034f545a2e982a5bb501..e6296868000c5f2ec6827cc7f9c724564e6a9da1 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5153,12 +5153,16 @@ public: return ExprEvalContexts.back(); }; - const ExpressionEvaluationContextRecord &parentEvaluationContext() const { + ExpressionEvaluationContextRecord &parentEvaluationContext() { assert(ExprEvalContexts.size() >= 2 && "Must be in an expression evaluation context"); return ExprEvalContexts[ExprEvalContexts.size() - 2]; }; + const ExpressionEvaluationContextRecord &parentEvaluationContext() const { + return const_cast(this)->parentEvaluationContext(); + }; + bool isBoundsAttrContext() const { return ExprEvalContexts.back().ExprContext == ExpressionEvaluationContextRecord::ExpressionKind:: @@ -6289,10 +6293,9 @@ public: /// flag from previous context. void keepInLifetimeExtendingContext() { if (ExprEvalContexts.size() > 2 && - ExprEvalContexts[ExprEvalContexts.size() - 2] - .InLifetimeExtendingContext) { + parentEvaluationContext().InLifetimeExtendingContext) { auto &LastRecord = ExprEvalContexts.back(); - auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2]; + auto &PrevRecord = parentEvaluationContext(); LastRecord.InLifetimeExtendingContext = PrevRecord.InLifetimeExtendingContext; } @@ -8985,6 +8988,9 @@ public: const TemplateArgumentListInfo *TemplateArgs); void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc); + void diagnoseMissingTemplateArguments(const CXXScopeSpec &SS, + bool TemplateKeyword, TemplateDecl *TD, + SourceLocation Loc); ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index 6f69fa08939b82d3ed553fd0f255ed9bfbafbc45..66144de4340a8a3827c011ffe315cce190c37711 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -379,7 +379,7 @@ public: /// Called after the construct has been parsed, but clauses haven't been /// parsed. This allows us to diagnose not-implemented, as well as set up any /// state required for parsing the clauses. - void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation StartLoc); + void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation DirLoc); /// Called after the directive, including its clauses, have been parsed and /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES @@ -400,6 +400,7 @@ public: /// declaration group or associated statement. StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, + SourceLocation DirLoc, SourceLocation EndLoc, ArrayRef Clauses, StmtResult AssocStmt); diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 1bb5fa27a2419e75e14baae1f4d625c171e91bf9..4ece4593f073837f48a096410d95c134cb844405 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -601,11 +601,11 @@ private: /// An array of lexical contents of a declaration context, as a sequence of /// Decl::Kind, DeclID pairs. - using unalighed_decl_id_t = + using unaligned_decl_id_t = llvm::support::detail::packed_endian_specific_integral< serialization::DeclID, llvm::endianness::native, llvm::support::unaligned>; - using LexicalContents = ArrayRef; + using LexicalContents = ArrayRef; /// Map from a DeclContext to its lexical contents. llvm::DenseMap> @@ -2246,7 +2246,7 @@ public: auto [Loc, ModuleFileIndex] = ReadUntranslatedSourceLocation(Raw, Seq); ModuleFile *OwningModuleFile = - ModuleFileIndex == 0 ? &MF : MF.DependentModules[ModuleFileIndex - 1]; + ModuleFileIndex == 0 ? &MF : MF.TransitiveImports[ModuleFileIndex - 1]; assert(!SourceMgr.isLoadedSourceLocation(Loc) && "Run out source location space"); diff --git a/clang/include/clang/Serialization/ModuleFile.h b/clang/include/clang/Serialization/ModuleFile.h index 7d8cbe3d40f56437d8ef3c2320a63353b77cd6b9..992d26a8b88c12d4dabb666b8de65ce97ce884ba 100644 --- a/clang/include/clang/Serialization/ModuleFile.h +++ b/clang/include/clang/Serialization/ModuleFile.h @@ -513,11 +513,11 @@ public: /// List of modules which this modules dependent on. Different /// from `Imports`, this includes indirectly imported modules too. - /// The order of DependentModules is significant. It should keep + /// The order of TransitiveImports is significant. It should keep /// the same order with that module file manager when we write /// the current module file. The value of the member will be initialized /// in `ASTReader::ReadModuleOffsetMap`. - llvm::SmallVector DependentModules; + llvm::SmallVector TransitiveImports; /// Determine whether this module was directly imported at /// any point during translation. diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index 8c77b563657d9073aa6cde9035d47c52cd9c32f0..d8e33ff421c06c8da15d2635c8ad02da062f8afb 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -90,7 +90,7 @@ QualType APValue::LValueBase::getType() const { // For a materialized temporary, the type of the temporary we materialized // may not be the type of the expression. if (const MaterializeTemporaryExpr *MTE = - clang::dyn_cast(Base)) { + llvm::dyn_cast(Base)) { SmallVector CommaLHSs; SmallVector Adjustments; const Expr *Temp = MTE->getSubExpr(); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index a2398fef623ea2143c119ebfda8563cead2627f3..06780ceba407465863502546e57b5435ab8d6dfe 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5006,9 +5006,6 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, QualType Underlying) const { assert(!Template.getAsDependentTemplateName() && "No dependent template names here!"); - // Look through qualified template names. - if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) - Template = QTN->getUnderlyingTemplate(); const auto *TD = Template.getAsTemplateDecl(); bool IsTypeAlias = TD && TD->isTypeAlias(); @@ -5044,10 +5041,6 @@ QualType ASTContext::getCanonicalTemplateSpecializationType( assert(!Template.getAsDependentTemplateName() && "No dependent template names here!"); - // Look through qualified template names. - if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) - Template = TemplateName(QTN->getUnderlyingTemplate()); - // Build the canonical template specialization type. TemplateName CanonTemplate = getCanonicalTemplateName(Template); bool AnyNonCanonArgs = false; @@ -5262,10 +5255,12 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) { Arg = TemplateArgument(E); } else { auto *TTP = cast(Param); + TemplateName Name = getQualifiedTemplateName( + nullptr, /*TemplateKeyword=*/false, TemplateName(TTP)); if (TTP->isParameterPack()) - Arg = TemplateArgument(TemplateName(TTP), std::optional()); + Arg = TemplateArgument(Name, std::optional()); else - Arg = TemplateArgument(TemplateName(TTP)); + Arg = TemplateArgument(Name); } if (Param->isTemplateParameterPack()) @@ -9304,7 +9299,8 @@ TemplateName ASTContext::getAssumedTemplateName(DeclarationName Name) const { TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, TemplateName Template) const { - assert(NNS && "Missing nested-name-specifier in qualified template name"); + assert(Template.getKind() == TemplateName::Template || + Template.getKind() == TemplateName::UsingTemplate); // FIXME: Canonicalization? llvm::FoldingSetNodeID ID; diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 95ffd4784641fcedef21ac67cad6affec8b8703d..d952f7e181848b4febc8383e90100e8567600f63 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -627,9 +627,10 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() { TemplateParameterList *Params = getTemplateParameters(); SmallVector TemplateArgs; Context.getInjectedTemplateArgs(Params, TemplateArgs); - CommonPtr->InjectedClassNameType - = Context.getTemplateSpecializationType(TemplateName(this), - TemplateArgs); + TemplateName Name = Context.getQualifiedTemplateName( + /*NNS=*/nullptr, /*TemplateKeyword=*/false, TemplateName(this)); + CommonPtr->InjectedClassNameType = + Context.getTemplateSpecializationType(Name, TemplateArgs); return CommonPtr->InjectedClassNameType; } diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 6607727b5246f591d8f65173ff2b96e89c09a013..3eb7e7544df71393dfefe97e5ee07e228d7dc48f 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -1637,6 +1637,12 @@ bool ByteCodeExprGen::VisitStringLiteral(const StringLiteral *E) { return true; } +template +bool ByteCodeExprGen::VisitObjCStringLiteral( + const ObjCStringLiteral *E) { + return this->delegate(E->getString()); +} + template bool ByteCodeExprGen::VisitSYCLUniqueStableNameExpr( const SYCLUniqueStableNameExpr *E) { @@ -2643,6 +2649,14 @@ bool ByteCodeExprGen::VisitShuffleVectorExpr( return true; } +template +bool ByteCodeExprGen::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) { + if (!E->isExpressibleAsConstantInitializer()) + return this->emitInvalid(E); + + return this->delegate(E->getSubExpr()); +} + template bool ByteCodeExprGen::discard(const Expr *E) { OptionScope Scope(this, /*NewDiscardResult=*/true, /*NewInitializing=*/false); @@ -2658,6 +2672,9 @@ bool ByteCodeExprGen::delegate(const Expr *E) { } template bool ByteCodeExprGen::visit(const Expr *E) { + if (E->getType().isNull()) + return false; + if (E->getType()->isVoidType()) return this->discard(E); @@ -3324,7 +3341,8 @@ bool ByteCodeExprGen::VisitCallExpr(const CallExpr *E) { // write the result into. if (IsVirtual && !HasQualifier) { uint32_t VarArgSize = 0; - unsigned NumParams = Func->getNumWrittenParams(); + unsigned NumParams = + Func->getNumWrittenParams() + isa(E); for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I) VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr))); @@ -3758,13 +3776,13 @@ bool ByteCodeExprGen::VisitDeclRefExpr(const DeclRefExpr *E) { return this->emitGetPtrLocal(Offset, E); } else if (auto GlobalIndex = P.getGlobal(D)) { if (IsReference) - return this->emitGetGlobalPtr(*GlobalIndex, E); + return this->emitGetGlobal(classifyPrim(E), *GlobalIndex, E); return this->emitGetPtrGlobal(*GlobalIndex, E); } else if (const auto *PVD = dyn_cast(D)) { if (auto It = this->Params.find(PVD); It != this->Params.end()) { if (IsReference || !It->second.IsPtr) - return this->emitGetParamPtr(It->second.Offset, E); + return this->emitGetParam(classifyPrim(E), It->second.Offset, E); return this->emitGetPtrParam(It->second.Offset, E); } diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index a2e283c86633251f9d4e725c15c696716c40d4cb..44c495240289f8b7251c776120762c2670aaceea 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -90,6 +90,7 @@ public: bool VisitOpaqueValueExpr(const OpaqueValueExpr *E); bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E); bool VisitStringLiteral(const StringLiteral *E); + bool VisitObjCStringLiteral(const ObjCStringLiteral *E); bool VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E); bool VisitCharacterLiteral(const CharacterLiteral *E); bool VisitCompoundAssignOperator(const CompoundAssignOperator *E); @@ -126,6 +127,7 @@ public: bool VisitAddrLabelExpr(const AddrLabelExpr *E); bool VisitConvertVectorExpr(const ConvertVectorExpr *E); bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E); + bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E); protected: bool visitExpr(const Expr *E) override; diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp index ff92bc117f9efb4082701089bb29b7cb4e10361d..6ee7898f228de41654a919e4c27d8cfedfb19c57 100644 --- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -687,26 +687,29 @@ bool ByteCodeStmtGen::visitDefaultStmt(const DefaultStmt *S) { template bool ByteCodeStmtGen::visitAttributedStmt(const AttributedStmt *S) { - for (const Attr *A : S->getAttrs()) { - auto *AA = dyn_cast(A); - if (!AA) - continue; + if (this->Ctx.getLangOpts().CXXAssumptions && + !this->Ctx.getLangOpts().MSVCCompat) { + for (const Attr *A : S->getAttrs()) { + auto *AA = dyn_cast(A); + if (!AA) + continue; - assert(isa(S->getSubStmt())); + assert(isa(S->getSubStmt())); - const Expr *Assumption = AA->getAssumption(); - if (Assumption->isValueDependent()) - return false; + const Expr *Assumption = AA->getAssumption(); + if (Assumption->isValueDependent()) + return false; - if (Assumption->HasSideEffects(this->Ctx.getASTContext())) - continue; + if (Assumption->HasSideEffects(this->Ctx.getASTContext())) + continue; - // Evaluate assumption. - if (!this->visitBool(Assumption)) - return false; + // Evaluate assumption. + if (!this->visitBool(Assumption)) + return false; - if (!this->emitAssume(Assumption)) - return false; + if (!this->emitAssume(Assumption)) + return false; + } } // Ignore other attributes. diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp index d51a57e5e92eae17070b18116d16a1d59e9f486f..4ecfa0f9bfd75170c9120d9d4a065e1d81931497 100644 --- a/clang/lib/AST/Interp/Context.cpp +++ b/clang/lib/AST/Interp/Context.cpp @@ -164,7 +164,8 @@ std::optional Context::classify(QualType T) const { T->isFunctionType() || T->isSpecificBuiltinType(BuiltinType::BoundMember)) return PT_FnPtr; - if (T->isReferenceType() || T->isPointerType()) + if (T->isReferenceType() || T->isPointerType() || + T->isObjCObjectPointerType()) return PT_Ptr; if (const auto *AT = T->getAs()) diff --git a/clang/lib/AST/Interp/PrimType.h b/clang/lib/AST/Interp/PrimType.h index 05a094d0c5b1ff122160b900448d89373d0668f9..604fb5dfde1e416983fb7028bc3d3b7c71e23ca9 100644 --- a/clang/lib/AST/Interp/PrimType.h +++ b/clang/lib/AST/Interp/PrimType.h @@ -30,20 +30,20 @@ template class Integral; /// Enumeration of the primitive types of the VM. enum PrimType : unsigned { - PT_Sint8, - PT_Uint8, - PT_Sint16, - PT_Uint16, - PT_Sint32, - PT_Uint32, - PT_Sint64, - PT_Uint64, - PT_IntAP, - PT_IntAPS, - PT_Bool, - PT_Float, - PT_Ptr, - PT_FnPtr, + PT_Sint8 = 0, + PT_Uint8 = 1, + PT_Sint16 = 2, + PT_Uint16 = 3, + PT_Sint32 = 4, + PT_Uint32 = 5, + PT_Sint64 = 6, + PT_Uint64 = 7, + PT_IntAP = 8, + PT_IntAPS = 9, + PT_Bool = 10, + PT_Float = 11, + PT_Ptr = 12, + PT_FnPtr = 13, }; inline constexpr bool isPtrType(PrimType T) { diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 246e56231539ae2025bb3ae2e8cd3ef3ecf1ecec..1249531eab09fcda73741cf0a63af4ff022c7a75 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -146,10 +146,17 @@ void ODRHash::AddTemplateName(TemplateName Name) { case TemplateName::Template: AddDecl(Name.getAsTemplateDecl()); break; + case TemplateName::QualifiedTemplate: { + QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName(); + if (NestedNameSpecifier *NNS = QTN->getQualifier()) + AddNestedNameSpecifier(NNS); + AddBoolean(QTN->hasTemplateKeyword()); + AddTemplateName(QTN->getUnderlyingTemplate()); + break; + } // TODO: Support these cases. case TemplateName::OverloadedTemplate: case TemplateName::AssumedTemplate: - case TemplateName::QualifiedTemplate: case TemplateName::DependentTemplate: case TemplateName::SubstTemplateTemplateParm: case TemplateName::SubstTemplateTemplateParmPack: diff --git a/clang/lib/AST/StmtOpenACC.cpp b/clang/lib/AST/StmtOpenACC.cpp index a381a8dd7b62c30a1fb0fdf7ddd5e3b24f0eb9b0..47899b344c97ab206059584af851845ded140671 100644 --- a/clang/lib/AST/StmtOpenACC.cpp +++ b/clang/lib/AST/StmtOpenACC.cpp @@ -23,15 +23,14 @@ OpenACCComputeConstruct::CreateEmpty(const ASTContext &C, unsigned NumClauses) { return Inst; } -OpenACCComputeConstruct * -OpenACCComputeConstruct::Create(const ASTContext &C, OpenACCDirectiveKind K, - SourceLocation BeginLoc, SourceLocation EndLoc, - ArrayRef Clauses, - Stmt *StructuredBlock) { +OpenACCComputeConstruct *OpenACCComputeConstruct::Create( + const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc, + SourceLocation DirLoc, SourceLocation EndLoc, + ArrayRef Clauses, Stmt *StructuredBlock) { void *Mem = C.Allocate( OpenACCComputeConstruct::totalSizeToAlloc( Clauses.size())); - auto *Inst = new (Mem) - OpenACCComputeConstruct(K, BeginLoc, EndLoc, Clauses, StructuredBlock); + auto *Inst = new (Mem) OpenACCComputeConstruct(K, BeginLoc, DirLoc, EndLoc, + Clauses, StructuredBlock); return Inst; } diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index a7ee973b7f7d0692dfa1290aa586b524e9077b0c..6d3c843cfd29e0a12380fd22e776d0d9335cd8cf 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -221,8 +221,13 @@ static const ValueDecl *getAsSimpleValueDeclRef(const ASTContext &Ctx, // We model class non-type template parameters as their template parameter // object declaration. - if (V.isStruct() || V.isUnion()) + if (V.isStruct() || V.isUnion()) { + // Dependent types are not supposed to be described as + // TemplateParamObjectDecls. + if (T->isDependentType() || T->isInstantiationDependentType()) + return nullptr; return Ctx.getTemplateParamObjectDecl(T, V); + } // Pointers and references with an empty path use the special 'Declaration' // representation. @@ -547,7 +552,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out, const auto *TTP = cast(TD); Out << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex(); } else { - TN.print(Out, Policy, TemplateName::Qualified::Fully); + TN.print(Out, Policy); } break; } diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp index 2f0e4181e9408668e360ea5697e3f771793697d0..3aae998eceeb052b27871ce3781756a81bf26f3a 100644 --- a/clang/lib/AST/TemplateName.cpp +++ b/clang/lib/AST/TemplateName.cpp @@ -235,8 +235,8 @@ TemplateNameDependence TemplateName::getDependence() const { auto D = TemplateNameDependence::None; switch (getKind()) { case TemplateName::NameKind::QualifiedTemplate: - D |= toTemplateNameDependence( - getAsQualifiedTemplateName()->getQualifier()->getDependence()); + if (NestedNameSpecifier *NNS = getAsQualifiedTemplateName()->getQualifier()) + D |= toTemplateNameDependence(NNS->getDependence()); break; case TemplateName::NameKind::DependentTemplate: D |= toTemplateNameDependence( @@ -292,9 +292,8 @@ void TemplateName::Profile(llvm::FoldingSetNodeID &ID) { void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, Qualified Qual) const { - auto Kind = getKind(); - TemplateDecl *Template = nullptr; - if (Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) { + if (NameKind Kind = getKind(); + Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) { // After `namespace ns { using std::vector }`, what is the fully-qualified // name of the UsingTemplateName `vector` within ns? // @@ -304,46 +303,43 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, // Similar to the UsingType behavior, using declarations are used to import // names more often than to export them, thus using the original name is // most useful in this case. - Template = getAsTemplateDecl(); - } - - if (Template) - if (Policy.CleanUglifiedParameters && - isa(Template) && Template->getIdentifier()) - OS << Template->getIdentifier()->deuglifiedName(); - else if (Qual == Qualified::Fully && - getDependence() != - TemplateNameDependenceScope::DependentInstantiation) - Template->printQualifiedName(OS, Policy); - else + TemplateDecl *Template = getAsTemplateDecl(); + if (Qual == Qualified::None) OS << *Template; - else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { - if (Qual == Qualified::Fully && - getDependence() != - TemplateNameDependenceScope::DependentInstantiation) { - QTN->getUnderlyingTemplate().getAsTemplateDecl()->printQualifiedName( - OS, Policy); - return; - } - if (Qual == Qualified::AsWritten) - QTN->getQualifier()->print(OS, Policy); + else + Template->printQualifiedName(OS, Policy); + } else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { + if (NestedNameSpecifier *NNS = QTN->getQualifier(); + Qual != Qualified::None && NNS) + NNS->print(OS, Policy); if (QTN->hasTemplateKeyword()) OS << "template "; - OS << *QTN->getUnderlyingTemplate().getAsTemplateDecl(); + + TemplateName Underlying = QTN->getUnderlyingTemplate(); + assert(Underlying.getKind() == TemplateName::Template || + Underlying.getKind() == TemplateName::UsingTemplate); + + TemplateDecl *UTD = Underlying.getAsTemplateDecl(); + if (IdentifierInfo *II = UTD->getIdentifier(); + Policy.CleanUglifiedParameters && II && + isa(UTD)) + OS << II->deuglifiedName(); + else + OS << *UTD; } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { - if (Qual == Qualified::AsWritten && DTN->getQualifier()) - DTN->getQualifier()->print(OS, Policy); + if (NestedNameSpecifier *NNS = DTN->getQualifier()) + NNS->print(OS, Policy); OS << "template "; if (DTN->isIdentifier()) OS << DTN->getIdentifier()->getName(); else OS << "operator " << getOperatorSpelling(DTN->getOperator()); - } else if (SubstTemplateTemplateParmStorage *subst - = getAsSubstTemplateTemplateParm()) { + } else if (SubstTemplateTemplateParmStorage *subst = + getAsSubstTemplateTemplateParm()) { subst->getReplacement().print(OS, Policy, Qual); - } else if (SubstTemplateTemplateParmPackStorage *SubstPack - = getAsSubstTemplateTemplateParmPack()) + } else if (SubstTemplateTemplateParmPackStorage *SubstPack = + getAsSubstTemplateTemplateParmPack()) OS << *SubstPack->getParameterPack(); else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) { Assumed->getDeclName().print(OS, Policy); diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 4a1e94ffe283ba3eebc78f595b06c40cd4b113a8..a0eedc71ea220be384e4b1edba6b65ccb7ceba32 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -947,6 +947,26 @@ void TextNodeDumper::dumpDeclRef(const Decl *D, StringRef Label) { }); } +void TextNodeDumper::dumpTemplateArgument(const TemplateArgument &TA) { + llvm::SmallString<128> Str; + { + llvm::raw_svector_ostream SS(Str); + TA.print(PrintPolicy, SS, /*IncludeType=*/true); + } + OS << " '" << Str << "'"; + + if (TemplateArgument CanonTA = Context->getCanonicalTemplateArgument(TA); + !CanonTA.structurallyEquals(TA)) { + llvm::SmallString<128> CanonStr; + { + llvm::raw_svector_ostream SS(CanonStr); + CanonTA.print(PrintPolicy, SS, /*IncludeType=*/true); + } + if (CanonStr != Str) + OS << ":'" << CanonStr << "'"; + } +} + const char *TextNodeDumper::getCommandName(unsigned CommandID) { if (Traits) return Traits->getCommandInfo(CommandID)->Name; @@ -1086,45 +1106,101 @@ void TextNodeDumper::VisitNullTemplateArgument(const TemplateArgument &) { void TextNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) { OS << " type"; - dumpType(TA.getAsType()); + dumpTemplateArgument(TA); } void TextNodeDumper::VisitDeclarationTemplateArgument( const TemplateArgument &TA) { OS << " decl"; + dumpTemplateArgument(TA); dumpDeclRef(TA.getAsDecl()); } -void TextNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &) { +void TextNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &TA) { OS << " nullptr"; + dumpTemplateArgument(TA); } void TextNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) { - OS << " integral " << TA.getAsIntegral(); + OS << " integral"; + dumpTemplateArgument(TA); +} + +void TextNodeDumper::dumpTemplateName(TemplateName TN) { + switch (TN.getKind()) { + case TemplateName::Template: + AddChild([=] { Visit(TN.getAsTemplateDecl()); }); + return; + case TemplateName::UsingTemplate: { + const UsingShadowDecl *USD = TN.getAsUsingShadowDecl(); + AddChild([=] { Visit(USD); }); + AddChild("target", [=] { Visit(USD->getTargetDecl()); }); + return; + } + case TemplateName::QualifiedTemplate: { + OS << " qualified"; + const QualifiedTemplateName *QTN = TN.getAsQualifiedTemplateName(); + if (QTN->hasTemplateKeyword()) + OS << " keyword"; + dumpNestedNameSpecifier(QTN->getQualifier()); + dumpTemplateName(QTN->getUnderlyingTemplate()); + return; + } + case TemplateName::DependentTemplate: { + OS << " dependent"; + const DependentTemplateName *DTN = TN.getAsDependentTemplateName(); + dumpNestedNameSpecifier(DTN->getQualifier()); + return; + } + case TemplateName::SubstTemplateTemplateParm: { + OS << " subst"; + const SubstTemplateTemplateParmStorage *STS = + TN.getAsSubstTemplateTemplateParm(); + OS << " index " << STS->getIndex(); + if (std::optional PackIndex = STS->getPackIndex()) + OS << " pack_index " << *PackIndex; + if (const TemplateTemplateParmDecl *P = STS->getParameter()) + AddChild("parameter", [=] { Visit(P); }); + dumpDeclRef(STS->getAssociatedDecl(), "associated"); + AddChild("replacement", [=] { dumpTemplateName(STS->getReplacement()); }); + return; + } + // FIXME: Implement these. + case TemplateName::OverloadedTemplate: + OS << " overloaded"; + return; + case TemplateName::AssumedTemplate: + OS << " assumed"; + return; + case TemplateName::SubstTemplateTemplateParmPack: + OS << " subst_pack"; + return; + } + llvm_unreachable("Unexpected TemplateName Kind"); } void TextNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) { - if (TA.getAsTemplate().getKind() == TemplateName::UsingTemplate) - OS << " using"; - OS << " template "; - TA.getAsTemplate().dump(OS); + OS << " template"; + dumpTemplateArgument(TA); + dumpTemplateName(TA.getAsTemplate()); } void TextNodeDumper::VisitTemplateExpansionTemplateArgument( const TemplateArgument &TA) { - if (TA.getAsTemplateOrTemplatePattern().getKind() == - TemplateName::UsingTemplate) - OS << " using"; - OS << " template expansion "; - TA.getAsTemplateOrTemplatePattern().dump(OS); + OS << " template expansion"; + dumpTemplateArgument(TA); + dumpTemplateName(TA.getAsTemplateOrTemplatePattern()); } -void TextNodeDumper::VisitExpressionTemplateArgument(const TemplateArgument &) { +void TextNodeDumper::VisitExpressionTemplateArgument( + const TemplateArgument &TA) { OS << " expr"; + dumpTemplateArgument(TA); } -void TextNodeDumper::VisitPackTemplateArgument(const TemplateArgument &) { +void TextNodeDumper::VisitPackTemplateArgument(const TemplateArgument &TA) { OS << " pack"; + dumpTemplateArgument(TA); } static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) { @@ -1913,7 +1989,7 @@ void TextNodeDumper::VisitAutoType(const AutoType *T) { void TextNodeDumper::VisitDeducedTemplateSpecializationType( const DeducedTemplateSpecializationType *T) { - if (T->getTemplateName().getKind() == TemplateName::UsingTemplate) + if (T->getTemplateName().getAsUsingShadowDecl()) OS << " using"; } @@ -1921,7 +1997,7 @@ void TextNodeDumper::VisitTemplateSpecializationType( const TemplateSpecializationType *T) { if (T->isTypeAlias()) OS << " alias"; - if (T->getTemplateName().getKind() == TemplateName::UsingTemplate) + if (T->getTemplateName().getAsUsingShadowDecl()) OS << " using"; OS << " "; T->getTemplateName().dump(OS); diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 04f105c12887216ec90d23ae5e835a1e6eb48029..2097b29b7e0b6d972ea562938ddc375c9af2a414 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -4251,7 +4251,8 @@ TemplateSpecializationType::TemplateSpecializationType( assert((T.getKind() == TemplateName::Template || T.getKind() == TemplateName::SubstTemplateTemplateParm || T.getKind() == TemplateName::SubstTemplateTemplateParmPack || - T.getKind() == TemplateName::UsingTemplate) && + T.getKind() == TemplateName::UsingTemplate || + T.getKind() == TemplateName::QualifiedTemplate) && "Unexpected template name for TemplateSpecializationType"); auto *TemplateArgs = reinterpret_cast(this + 1); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 5ed56b367a46a7ede21e7c3ccb3a79aa0948840f..58d01705d607b27825d6824201c43fd1f6d07b06 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1586,14 +1586,14 @@ void TypePrinter::printTemplateId(const TemplateSpecializationType *T, IncludeStrongLifetimeRAII Strong(Policy); TemplateDecl *TD = T->getTemplateName().getAsTemplateDecl(); - // FIXME: Null TD never excercised in test suite. + // FIXME: Null TD never exercised in test suite. if (FullyQualify && TD) { if (!Policy.SuppressScope) AppendScope(TD->getDeclContext(), OS, TD->getDeclName()); OS << TD->getName(); } else { - T->getTemplateName().print(OS, Policy); + T->getTemplateName().print(OS, Policy, TemplateName::Qualified::None); } DefaultTemplateArgsPolicyRAII TemplateArgs(Policy); diff --git a/clang/lib/Analysis/MacroExpansionContext.cpp b/clang/lib/Analysis/MacroExpansionContext.cpp index 564e359668a5106a6d00dd5c81b7ce4e458ab262..b212b7f2457927c9affae19963a97251b688fa7e 100644 --- a/clang/lib/Analysis/MacroExpansionContext.cpp +++ b/clang/lib/Analysis/MacroExpansionContext.cpp @@ -12,7 +12,7 @@ #define DEBUG_TYPE "macro-expansion-context" -static void dumpTokenInto(const clang::Preprocessor &PP, clang::raw_ostream &OS, +static void dumpTokenInto(const clang::Preprocessor &PP, llvm::raw_ostream &OS, clang::Token Tok); namespace clang { diff --git a/clang/lib/Basic/CharInfo.cpp b/clang/lib/Basic/CharInfo.cpp index d02054c9718f5fba694de81aa8faa33fe3642f5d..26d693b8e9b943f9e1f44810e7dbff4d07011e41 100644 --- a/clang/lib/Basic/CharInfo.cpp +++ b/clang/lib/Basic/CharInfo.cpp @@ -31,20 +31,20 @@ const uint16_t clang::charinfo::InfoTable[256] = { 0 , 0 , 0 , 0 , //32 SP 33 ! 34 " 35 # //36 $ 37 % 38 & 39 ' - CHAR_SPACE , CHAR_RAWDEL , CHAR_RAWDEL , CHAR_RAWDEL , - CHAR_PUNCT , CHAR_RAWDEL , CHAR_RAWDEL , CHAR_RAWDEL , + CHAR_SPACE , CHAR_PUNCT , CHAR_PUNCT , CHAR_PUNCT , + CHAR_PUNCT , CHAR_PUNCT , CHAR_PUNCT , CHAR_PUNCT , //40 ( 41 ) 42 * 43 + //44 , 45 - 46 . 47 / - CHAR_PUNCT , CHAR_PUNCT , CHAR_RAWDEL , CHAR_RAWDEL , - CHAR_RAWDEL , CHAR_RAWDEL , CHAR_PERIOD , CHAR_RAWDEL , + CHAR_PUNCT , CHAR_PUNCT , CHAR_PUNCT , CHAR_PUNCT , + CHAR_PUNCT , CHAR_PUNCT , CHAR_PERIOD , CHAR_PUNCT , //48 0 49 1 50 2 51 3 //52 4 53 5 54 6 55 7 CHAR_DIGIT , CHAR_DIGIT , CHAR_DIGIT , CHAR_DIGIT , CHAR_DIGIT , CHAR_DIGIT , CHAR_DIGIT , CHAR_DIGIT , //56 8 57 9 58 : 59 ; //60 < 61 = 62 > 63 ? - CHAR_DIGIT , CHAR_DIGIT , CHAR_RAWDEL , CHAR_RAWDEL , - CHAR_RAWDEL , CHAR_RAWDEL , CHAR_RAWDEL , CHAR_RAWDEL , + CHAR_DIGIT , CHAR_DIGIT , CHAR_PUNCT , CHAR_PUNCT , + CHAR_PUNCT , CHAR_PUNCT , CHAR_PUNCT , CHAR_PUNCT , //64 @ 65 A 66 B 67 C //68 D 69 E 70 F 71 G CHAR_PUNCT , CHAR_XUPPER , CHAR_XUPPER , CHAR_XUPPER , @@ -59,8 +59,8 @@ const uint16_t clang::charinfo::InfoTable[256] = { CHAR_UPPER , CHAR_UPPER , CHAR_UPPER , CHAR_UPPER , //88 X 89 Y 90 Z 91 [ //92 \ 93 ] 94 ^ 95 _ - CHAR_UPPER , CHAR_UPPER , CHAR_UPPER , CHAR_RAWDEL , - CHAR_PUNCT , CHAR_RAWDEL , CHAR_RAWDEL , CHAR_UNDER , + CHAR_UPPER , CHAR_UPPER , CHAR_UPPER , CHAR_PUNCT , + CHAR_PUNCT , CHAR_PUNCT , CHAR_PUNCT , CHAR_UNDER , //96 ` 97 a 98 b 99 c //100 d 101 e 102 f 103 g CHAR_PUNCT , CHAR_XLOWER , CHAR_XLOWER , CHAR_XLOWER , @@ -75,6 +75,6 @@ const uint16_t clang::charinfo::InfoTable[256] = { CHAR_LOWER , CHAR_LOWER , CHAR_LOWER , CHAR_LOWER , //120 x 121 y 122 z 123 { //124 | 125 } 126 ~ 127 DEL - CHAR_LOWER , CHAR_LOWER , CHAR_LOWER , CHAR_RAWDEL , - CHAR_RAWDEL , CHAR_RAWDEL , CHAR_RAWDEL , 0 + CHAR_LOWER , CHAR_LOWER , CHAR_LOWER , CHAR_PUNCT , + CHAR_PUNCT , CHAR_PUNCT , CHAR_PUNCT , 0 }; diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index 3a30cff917bb4fa8a69817598eb7b0edf3fee035..08e44360bfbe38e66cf05e97aeb9357b9f3821b3 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -961,7 +961,7 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts, if (HasCF) Builder.defineMacro("__CF__"); // Condition here is aligned with the feature set of mapxf in Options.td - if (HasEGPR && HasPush2Pop2 && HasPPX && HasNDD) + if (HasEGPR && HasPush2Pop2 && HasPPX && HasNDD && HasCCMP && HasNF) Builder.defineMacro("__APX_F__"); // Each case falls through to the previous one here. diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 0549afa12e430d9871ebceeb54dcb4d96f699c4e..266bf41fd5577cbcf1e8ee305e679d97b34e8fca 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -57,6 +57,7 @@ #include "llvm/IR/IntrinsicsX86.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/MatrixBuilder.h" +#include "llvm/IR/MemoryModelRelaxationAnnotations.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/ScopedPrinter.h" @@ -14073,7 +14074,7 @@ Value *CodeGenFunction::EmitX86CpuIs(StringRef CPUStr) { // Grab the appropriate field from __cpu_model. llvm::Value *Idxs[] = {ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, Index)}; - llvm::Value *CpuValue = Builder.CreateGEP(STy, CpuModel, Idxs); + llvm::Value *CpuValue = Builder.CreateInBoundsGEP(STy, CpuModel, Idxs); CpuValue = Builder.CreateAlignedLoad(Int32Ty, CpuValue, CharUnits::fromQuantity(4)); @@ -14115,7 +14116,7 @@ CodeGenFunction::EmitX86CpuSupports(std::array FeatureMask) { // global in the struct STy. Value *Idxs[] = {Builder.getInt32(0), Builder.getInt32(3), Builder.getInt32(0)}; - Value *CpuFeatures = Builder.CreateGEP(STy, CpuModel, Idxs); + Value *CpuFeatures = Builder.CreateInBoundsGEP(STy, CpuModel, Idxs); Value *Features = Builder.CreateAlignedLoad(Int32Ty, CpuFeatures, CharUnits::fromQuantity(4)); @@ -14136,7 +14137,7 @@ CodeGenFunction::EmitX86CpuSupports(std::array FeatureMask) { continue; Value *Idxs[] = {Builder.getInt32(0), Builder.getInt32(i - 1)}; Value *Features = Builder.CreateAlignedLoad( - Int32Ty, Builder.CreateGEP(ATy, CpuFeatures2, Idxs), + Int32Ty, Builder.CreateInBoundsGEP(ATy, CpuFeatures2, Idxs), CharUnits::fromQuantity(4)); // Check the value of the bit corresponding to the feature requested. Value *Mask = Builder.getInt32(M); @@ -16723,7 +16724,7 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, llvm::Value *Idxs[] = {ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, FieldIdx)}; - FieldValue = Builder.CreateGEP(STy, SysConf, Idxs); + FieldValue = Builder.CreateInBoundsGEP(STy, SysConf, Idxs); FieldValue = Builder.CreateAlignedLoad(Int32Ty, FieldValue, CharUnits::fromQuantity(4)); } else if (SupportMethod == SYS_CALL) { @@ -18327,6 +18328,29 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return nullptr; } +void CodeGenFunction::AddAMDGPUFenceAddressSpaceMMRA(llvm::Instruction *Inst, + const CallExpr *E) { + constexpr const char *Tag = "amdgpu-as"; + + LLVMContext &Ctx = Inst->getContext(); + SmallVector MMRAs; + for (unsigned K = 2; K < E->getNumArgs(); ++K) { + llvm::Value *V = EmitScalarExpr(E->getArg(K)); + StringRef AS; + if (llvm::getConstantStringInfo(V, AS)) { + MMRAs.push_back({Tag, AS}); + // TODO: Delete the resulting unused constant? + continue; + } + CGM.Error(E->getExprLoc(), + "expected an address space name as a string literal"); + } + + llvm::sort(MMRAs); + MMRAs.erase(llvm::unique(MMRAs), MMRAs.end()); + Inst->setMetadata(LLVMContext::MD_mmra, MMRAMetadata::getMD(Ctx, MMRAs)); +} + Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { llvm::AtomicOrdering AO = llvm::AtomicOrdering::SequentiallyConsistent; @@ -18997,7 +19021,10 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, case AMDGPU::BI__builtin_amdgcn_fence: { ProcessOrderScopeAMDGCN(EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)), AO, SSID); - return Builder.CreateFence(AO, SSID); + FenceInst *Fence = Builder.CreateFence(AO, SSID); + if (E->getNumArgs() > 2) + AddAMDGPUFenceAddressSpaceMMRA(Fence, E); + return Fence; } case AMDGPU::BI__builtin_amdgcn_atomic_inc32: case AMDGPU::BI__builtin_amdgcn_atomic_inc64: @@ -20779,6 +20806,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_min_f32: case WebAssembly::BI__builtin_wasm_min_f64: + case WebAssembly::BI__builtin_wasm_min_f16x8: case WebAssembly::BI__builtin_wasm_min_f32x4: case WebAssembly::BI__builtin_wasm_min_f64x2: { Value *LHS = EmitScalarExpr(E->getArg(0)); @@ -20789,6 +20817,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } case WebAssembly::BI__builtin_wasm_max_f32: case WebAssembly::BI__builtin_wasm_max_f64: + case WebAssembly::BI__builtin_wasm_max_f16x8: case WebAssembly::BI__builtin_wasm_max_f32x4: case WebAssembly::BI__builtin_wasm_max_f64x2: { Value *LHS = EmitScalarExpr(E->getArg(0)); @@ -20797,6 +20826,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, CGM.getIntrinsic(Intrinsic::maximum, ConvertType(E->getType())); return Builder.CreateCall(Callee, {LHS, RHS}); } + case WebAssembly::BI__builtin_wasm_pmin_f16x8: case WebAssembly::BI__builtin_wasm_pmin_f32x4: case WebAssembly::BI__builtin_wasm_pmin_f64x2: { Value *LHS = EmitScalarExpr(E->getArg(0)); @@ -20805,6 +20835,7 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, CGM.getIntrinsic(Intrinsic::wasm_pmin, ConvertType(E->getType())); return Builder.CreateCall(Callee, {LHS, RHS}); } + case WebAssembly::BI__builtin_wasm_pmax_f16x8: case WebAssembly::BI__builtin_wasm_pmax_f32x4: case WebAssembly::BI__builtin_wasm_pmax_f64x2: { Value *LHS = EmitScalarExpr(E->getArg(0)); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index fac278f0e20a438102c913384af3e48185e11c96..5f6f911c7a6d698d44324e94a85c0259f6ed7084 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2836,7 +2836,7 @@ CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { // Collect data fields (including static variables and any initializers). CollectRecordFields(RD, DefUnit, EltTys, FwdDecl); - if (CXXDecl) + if (CXXDecl && !CGM.getCodeGenOpts().DebugOmitUnreferencedMethods) CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl); LexicalBlockStack.pop_back(); @@ -5737,6 +5737,90 @@ void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var, Var->addDebugInfo(GVE); } +void CGDebugInfo::EmitPseudoVariable(CGBuilderTy &Builder, + llvm::Instruction *Value, QualType Ty) { + // Only when -g2 or above is specified, debug info for variables will be + // generated. + if (CGM.getCodeGenOpts().getDebugInfo() <= + llvm::codegenoptions::DebugLineTablesOnly) + return; + + llvm::DebugLoc SaveDebugLoc = Builder.getCurrentDebugLocation(); + if (!SaveDebugLoc.get()) + return; + + llvm::DIFile *Unit = SaveDebugLoc->getFile(); + llvm::DIType *Type = getOrCreateType(Ty, Unit); + + // Check if Value is already a declared variable and has debug info, in this + // case we have nothing to do. Clang emits declared variable as alloca, and + // it is loaded upon use, so we identify such pattern here. + if (llvm::LoadInst *Load = dyn_cast(Value)) { + llvm::Value *Var = Load->getPointerOperand(); + if (llvm::Metadata *MDValue = llvm::ValueAsMetadata::getIfExists(Var)) { + if (llvm::Value *DbgValue = llvm::MetadataAsValue::getIfExists( + CGM.getLLVMContext(), MDValue)) { + for (llvm::User *U : DbgValue->users()) { + if (llvm::CallInst *DbgDeclare = dyn_cast(U)) { + if (DbgDeclare->getCalledFunction()->getIntrinsicID() == + llvm::Intrinsic::dbg_declare && + DbgDeclare->getArgOperand(0) == DbgValue) { + // There can be implicit type cast applied on a variable if it is + // an opaque ptr, in this case its debug info may not match the + // actual type of object being used as in the next instruction, so + // we will need to emit a pseudo variable for type-casted value. + llvm::DILocalVariable *MDNode = cast( + cast(DbgDeclare->getOperand(1)) + ->getMetadata()); + if (MDNode->getType() == Type) + return; + } + } + } + } + } + } + + // Find the correct location to insert a sequence of instructions to + // materialize Value on the stack. + auto SaveInsertionPoint = Builder.saveIP(); + if (llvm::InvokeInst *Invoke = dyn_cast(Value)) + Builder.SetInsertPoint(Invoke->getNormalDest()->begin()); + else if (llvm::Instruction *Next = Value->getIterator()->getNextNode()) + Builder.SetInsertPoint(Next); + else + Builder.SetInsertPoint(Value->getParent()); + llvm::DebugLoc DL = Value->getDebugLoc(); + if (DL.get()) + Builder.SetCurrentDebugLocation(DL); + else if (!Builder.getCurrentDebugLocation().get()) + Builder.SetCurrentDebugLocation(SaveDebugLoc); + + llvm::AllocaInst *PseudoVar = Builder.CreateAlloca(Value->getType()); + Address PseudoVarAddr(PseudoVar, Value->getType(), + CharUnits::fromQuantity(PseudoVar->getAlign())); + llvm::LoadInst *Load = Builder.CreateLoad(PseudoVarAddr); + Value->replaceAllUsesWith(Load); + Builder.SetInsertPoint(Load); + Builder.CreateStore(Value, PseudoVarAddr); + + // Emit debug info for materialized Value. + unsigned Line = Builder.getCurrentDebugLocation().getLine(); + unsigned Column = Builder.getCurrentDebugLocation().getCol(); + llvm::DILocalVariable *D = DBuilder.createAutoVariable( + LexicalBlockStack.back(), "", nullptr, 0, Type, false, + llvm::DINode::FlagArtificial); + llvm::DILocation *DIL = + llvm::DILocation::get(CGM.getLLVMContext(), Line, Column, + LexicalBlockStack.back(), CurInlinedAt); + SmallVector Expr; + DBuilder.insertDeclare(PseudoVar, D, DBuilder.createExpression(Expr), DIL, + Load); + + Builder.restoreIP(SaveInsertionPoint); + Builder.SetCurrentDebugLocation(SaveDebugLoc); +} + void CGDebugInfo::EmitGlobalAlias(const llvm::GlobalValue *GV, const GlobalDecl GD) { diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index d6db4d711366accf43100ef70628bbb9f2d345e5..614316f3fc7fd8b34ed81314a276bd50ffd5f5e3 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -529,6 +529,12 @@ public: /// Emit information about an external variable. void EmitExternalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl); + /// Emit a pseudo variable and debug info for an intermediate value if it does + /// not correspond to a variable in the source code, so that a profiler can + /// track more accurate usage of certain instructions of interest. + void EmitPseudoVariable(CGBuilderTy &Builder, llvm::Instruction *Value, + QualType Ty); + /// Emit information about global variable alias. void EmitGlobalAlias(const llvm::GlobalValue *GV, const GlobalDecl Decl); diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index bba00257fd4f0aab44c479467597f3706e0c257f..7a92fc3dfb4a43471f2b215236adbd7d61acf3fd 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -1789,7 +1789,6 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr( // Push a destructor if necessary. // FIXME: if we have an array of structures, all explicitly // initialized, we can end up pushing a linear number of cleanups. - bool pushedCleanup = false; if (QualType::DestructionKind dtorKind = field->getType().isDestructedType()) { assert(LV.isSimple()); @@ -1797,17 +1796,8 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr( CGF.pushDestroyAndDeferDeactivation(NormalAndEHCleanup, LV.getAddress(), field->getType(), CGF.getDestroyer(dtorKind), false); - pushedCleanup = true; } } - - // If the GEP didn't get used because of a dead zero init or something - // else, clean it up for -O0 builds and general tidiness. - if (!pushedCleanup && LV.isSimple()) - if (llvm::GetElementPtrInst *GEP = - dyn_cast(LV.emitRawPointer(CGF))) - if (GEP->use_empty()) - GEP->eraseFromParent(); } } diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 1b144c178ce960656144793741b737e02f58b2b0..58f0a3113b4f8133741f659dce3fdc61b44fa54d 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -1937,7 +1937,26 @@ Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) { } } - return EmitLoadOfLValue(E); + llvm::Value *Result = EmitLoadOfLValue(E); + + // If -fdebug-info-for-profiling is specified, emit a pseudo variable and its + // debug info for the pointer, even if there is no variable associated with + // the pointer's expression. + if (CGF.CGM.getCodeGenOpts().DebugInfoForProfiling && CGF.getDebugInfo()) { + if (llvm::LoadInst *Load = dyn_cast(Result)) { + if (llvm::GetElementPtrInst *GEP = + dyn_cast(Load->getPointerOperand())) { + if (llvm::Instruction *Pointer = + dyn_cast(GEP->getPointerOperand())) { + QualType Ty = E->getBase()->getType(); + if (!E->isArrow()) + Ty = CGF.getContext().getPointerType(Ty); + CGF.getDebugInfo()->EmitPseudoVariable(Builder, Pointer, Ty); + } + } + } + } + return Result; } Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 5f3ee7eb943f9e17aa7a5a20579f6324228d1eda..45585361a4fc9960715c23c6f904af6f09b7f2a3 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4635,6 +4635,9 @@ public: llvm::Value *EmitHexagonBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitRISCVBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue); + + void AddAMDGPUFenceAddressSpaceMMRA(llvm::Instruction *Inst, + const CallExpr *E); void ProcessOrderScopeAMDGCN(llvm::Value *Order, llvm::Value *Scope, llvm::AtomicOrdering &AO, llvm::SyncScope::ID &SSID); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index e4774a587707ac39e88cd38d8d7cadc89ead3c01..0b0b659e1fd490a5cac369e536453f66fd388c7a 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -5341,6 +5341,18 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, !IsDefinitionAvailableExternally && D->needsDestruction(getContext()) == QualType::DK_cxx_destructor; + // It is helpless to emit the definition for an available_externally variable + // which can't be marked as const. + // We don't need to check if it needs global ctor or dtor. See the above + // comment for ideas. + if (IsDefinitionAvailableExternally && + (!D->hasConstantInitialization() || + // TODO: Update this when we have interface to check constexpr + // destructor. + D->needsDestruction(getContext()) || + !D->getType().isConstantStorage(getContext(), true, true))) + return; + const VarDecl *InitDecl; const Expr *InitExpr = D->getAnyInitializer(InitDecl); diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp index 76704c4d7be4a49de647c9f64aac615724215bb7..db8e6f55302adcb4b3f065e01a3dfcb409b98824 100644 --- a/clang/lib/CodeGen/CodeGenPGO.cpp +++ b/clang/lib/CodeGen/CodeGenPGO.cpp @@ -1340,7 +1340,7 @@ void CodeGenPGO::setProfileVersion(llvm::Module &M) { llvm::APInt(64, ProfileVersion)), VarName); - IRLevelVersionVariable->setVisibility(llvm::GlobalValue::DefaultVisibility); + IRLevelVersionVariable->setVisibility(llvm::GlobalValue::HiddenVisibility); llvm::Triple TT(M.getTargetTriple()); if (TT.supportsCOMDAT()) { IRLevelVersionVariable->setLinkage(llvm::GlobalValue::ExternalLinkage); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 97e451cfe2acb411d25828c14d9c65f8b78f7caa..4e1c52462e5842c8cce009195ab37e9fd9ff1e71 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -45,6 +45,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/BinaryFormat/Magic.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Frontend/Debug/Options.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/CodeGen.h" @@ -4642,6 +4643,7 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, Args.addOptInFlag(CmdArgs, options::OPT_fforce_dwarf_frame, options::OPT_fno_force_dwarf_frame); + bool EnableTypeUnits = false; if (Args.hasFlag(options::OPT_fdebug_types_section, options::OPT_fno_debug_types_section, false)) { if (!(T.isOSBinFormatELF() || T.isOSBinFormatWasm())) { @@ -4652,11 +4654,24 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, } else if (checkDebugInfoOption( Args.getLastArg(options::OPT_fdebug_types_section), Args, D, TC)) { + EnableTypeUnits = true; CmdArgs.push_back("-mllvm"); CmdArgs.push_back("-generate-type-units"); } } + if (const Arg *A = + Args.getLastArg(options::OPT_gomit_unreferenced_methods, + options::OPT_gno_omit_unreferenced_methods)) + (void)checkDebugInfoOption(A, Args, D, TC); + if (Args.hasFlag(options::OPT_gomit_unreferenced_methods, + options::OPT_gno_omit_unreferenced_methods, false) && + (DebugInfoKind == llvm::codegenoptions::DebugInfoConstructor || + DebugInfoKind == llvm::codegenoptions::LimitedDebugInfo) && + !EnableTypeUnits) { + CmdArgs.push_back("-gomit-unreferenced-methods"); + } + // To avoid join/split of directory+filename, the integrated assembler prefers // the directory form of .file on all DWARF versions. GNU as doesn't allow the // form before DWARF v5. diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 9849c59685cca78b6e1645ed7aa3d8a05cd9f182..f7611af5763ab7a13eb322bd27c973ce256f3aba 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -672,12 +672,41 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, } } + // Facebook T92898286 + if (Args.hasArg(options::OPT_post_link_optimize)) + CmdArgs.push_back("-q"); + // End Facebook T92898286 + Args.AddAllArgs(CmdArgs, options::OPT_T); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs, Output)); + // Facebook T92898286 + if (!Args.hasArg(options::OPT_post_link_optimize) || !Output.isFilename()) + return; + + const char *MvExec = Args.MakeArgString(ToolChain.GetProgramPath("mv")); + ArgStringList MoveCmdArgs; + MoveCmdArgs.push_back(Output.getFilename()); + const char *PreBoltBin = + Args.MakeArgString(Twine(Output.getFilename()) + ".pre-bolt"); + MoveCmdArgs.push_back(PreBoltBin); + C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), + MvExec, MoveCmdArgs, std::nullopt)); + + ArgStringList BoltCmdArgs; + const char *BoltExec = + Args.MakeArgString(ToolChain.GetProgramPath("llvm-bolt")); + BoltCmdArgs.push_back(PreBoltBin); + BoltCmdArgs.push_back("-reorder-blocks=reverse"); + BoltCmdArgs.push_back("-update-debug-sections"); + BoltCmdArgs.push_back("-o"); + BoltCmdArgs.push_back(Output.getFilename()); + C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), + BoltExec, BoltCmdArgs, std::nullopt)); + // End Facebook T92898286 } void tools::gnutools::Assembler::ConstructJob(Compilation &C, @@ -2227,10 +2256,19 @@ void Generic_GCC::GCCInstallationDetector::init( SmallVector CandidateBiarchTripleAliases; // Add some triples that we want to check first. CandidateTripleAliases.push_back(TargetTriple.str()); - std::string TripleNoVendor = TargetTriple.getArchName().str() + "-" + - TargetTriple.getOSAndEnvironmentName().str(); - if (TargetTriple.getVendor() == llvm::Triple::UnknownVendor) + std::string TripleNoVendor, BiarchTripleNoVendor; + if (TargetTriple.getVendor() == llvm::Triple::UnknownVendor) { + StringRef OSEnv = TargetTriple.getOSAndEnvironmentName(); + if (TargetTriple.getEnvironment() == llvm::Triple::GNUX32) + OSEnv = "linux-gnu"; + TripleNoVendor = (TargetTriple.getArchName().str() + '-' + OSEnv).str(); CandidateTripleAliases.push_back(TripleNoVendor); + if (BiarchVariantTriple.getArch() != llvm::Triple::UnknownArch) { + BiarchTripleNoVendor = + (BiarchVariantTriple.getArchName().str() + '-' + OSEnv).str(); + CandidateBiarchTripleAliases.push_back(BiarchTripleNoVendor); + } + } CollectLibDirsAndTriples(TargetTriple, BiarchVariantTriple, CandidateLibDirs, CandidateTripleAliases, CandidateBiarchLibDirs, @@ -2453,11 +2491,9 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( // lists should shrink over time. Please don't add more elements to *Triples. static const char *const AArch64LibDirs[] = {"/lib64", "/lib"}; static const char *const AArch64Triples[] = { - "aarch64-none-linux-gnu", "aarch64-linux-gnu", "aarch64-redhat-linux", - "aarch64-suse-linux"}; + "aarch64-none-linux-gnu", "aarch64-redhat-linux", "aarch64-suse-linux"}; static const char *const AArch64beLibDirs[] = {"/lib"}; - static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu", - "aarch64_be-linux-gnu"}; + static const char *const AArch64beTriples[] = {"aarch64_be-none-linux-gnu"}; static const char *const ARMLibDirs[] = {"/lib"}; static const char *const ARMTriples[] = {"arm-linux-gnueabi"}; @@ -2482,9 +2518,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( "x86_64-linux-gnu", "x86_64-unknown-linux-gnu", "x86_64-pc-linux-gnu", "x86_64-redhat-linux6E", "x86_64-redhat-linux", "x86_64-suse-linux", - "x86_64-manbo-linux-gnu", "x86_64-linux-gnu", - "x86_64-slackware-linux", "x86_64-unknown-linux", - "x86_64-amazon-linux"}; + "x86_64-manbo-linux-gnu", "x86_64-slackware-linux", + "x86_64-unknown-linux", "x86_64-amazon-linux"}; static const char *const X32Triples[] = {"x86_64-linux-gnux32", "x86_64-pc-linux-gnux32"}; static const char *const X32LibDirs[] = {"/libx32", "/lib"}; @@ -2500,26 +2535,24 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( "loongarch64-linux-gnu", "loongarch64-unknown-linux-gnu"}; static const char *const M68kLibDirs[] = {"/lib"}; - static const char *const M68kTriples[] = { - "m68k-linux-gnu", "m68k-unknown-linux-gnu", "m68k-suse-linux"}; + static const char *const M68kTriples[] = {"m68k-unknown-linux-gnu", + "m68k-suse-linux"}; static const char *const MIPSLibDirs[] = {"/libo32", "/lib"}; static const char *const MIPSTriples[] = { "mips-linux-gnu", "mips-mti-linux", "mips-mti-linux-gnu", "mips-img-linux-gnu", "mipsisa32r6-linux-gnu"}; static const char *const MIPSELLibDirs[] = {"/libo32", "/lib"}; - static const char *const MIPSELTriples[] = { - "mipsel-linux-gnu", "mips-img-linux-gnu", "mipsisa32r6el-linux-gnu"}; + static const char *const MIPSELTriples[] = {"mipsel-linux-gnu", + "mips-img-linux-gnu"}; static const char *const MIPS64LibDirs[] = {"/lib64", "/lib"}; static const char *const MIPS64Triples[] = { - "mips64-linux-gnu", "mips-mti-linux-gnu", - "mips-img-linux-gnu", "mips64-linux-gnuabi64", + "mips-mti-linux-gnu", "mips-img-linux-gnu", "mips64-linux-gnuabi64", "mipsisa64r6-linux-gnu", "mipsisa64r6-linux-gnuabi64"}; static const char *const MIPS64ELLibDirs[] = {"/lib64", "/lib"}; static const char *const MIPS64ELTriples[] = { - "mips64el-linux-gnu", "mips-mti-linux-gnu", - "mips-img-linux-gnu", "mips64el-linux-gnuabi64", + "mips-mti-linux-gnu", "mips-img-linux-gnu", "mips64el-linux-gnuabi64", "mipsisa64r6el-linux-gnu", "mipsisa64r6el-linux-gnuabi64"}; static const char *const MIPSN32LibDirs[] = {"/lib32"}; @@ -2534,46 +2567,39 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( static const char *const PPCLibDirs[] = {"/lib32", "/lib"}; static const char *const PPCTriples[] = { - "powerpc-linux-gnu", "powerpc-unknown-linux-gnu", "powerpc-linux-gnuspe", + "powerpc-unknown-linux-gnu", // On 32-bit PowerPC systems running SUSE Linux, gcc is configured as a // 64-bit compiler which defaults to "-m32", hence "powerpc64-suse-linux". "powerpc64-suse-linux", "powerpc-montavista-linuxspe"}; static const char *const PPCLELibDirs[] = {"/lib32", "/lib"}; - static const char *const PPCLETriples[] = {"powerpcle-linux-gnu", - "powerpcle-unknown-linux-gnu", + static const char *const PPCLETriples[] = {"powerpcle-unknown-linux-gnu", "powerpcle-linux-musl"}; static const char *const PPC64LibDirs[] = {"/lib64", "/lib"}; - static const char *const PPC64Triples[] = { - "powerpc64-linux-gnu", "powerpc64-unknown-linux-gnu", - "powerpc64-suse-linux", "ppc64-redhat-linux"}; + static const char *const PPC64Triples[] = {"powerpc64-unknown-linux-gnu", + "powerpc64-suse-linux", + "ppc64-redhat-linux"}; static const char *const PPC64LELibDirs[] = {"/lib64", "/lib"}; static const char *const PPC64LETriples[] = { - "powerpc64le-linux-gnu", "powerpc64le-unknown-linux-gnu", - "powerpc64le-none-linux-gnu", "powerpc64le-suse-linux", - "ppc64le-redhat-linux"}; + "powerpc64le-unknown-linux-gnu", "powerpc64le-none-linux-gnu", + "powerpc64le-suse-linux", "ppc64le-redhat-linux"}; static const char *const RISCV32LibDirs[] = {"/lib32", "/lib"}; static const char *const RISCV32Triples[] = {"riscv32-unknown-linux-gnu", - "riscv32-linux-gnu", "riscv32-unknown-elf"}; static const char *const RISCV64LibDirs[] = {"/lib64", "/lib"}; static const char *const RISCV64Triples[] = {"riscv64-unknown-linux-gnu", - "riscv64-linux-gnu", "riscv64-unknown-elf"}; static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"}; - static const char *const SPARCv8Triples[] = {"sparc-linux-gnu", - "sparcv8-linux-gnu"}; + static const char *const SPARCv8Triples[] = {"sparcv8-linux-gnu"}; static const char *const SPARCv9LibDirs[] = {"/lib64", "/lib"}; - static const char *const SPARCv9Triples[] = {"sparc64-linux-gnu", - "sparcv9-linux-gnu"}; + static const char *const SPARCv9Triples[] = {"sparcv9-linux-gnu"}; static const char *const SystemZLibDirs[] = {"/lib64", "/lib"}; static const char *const SystemZTriples[] = { - "s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu", - "s390x-suse-linux", "s390x-redhat-linux"}; - + "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu", "s390x-suse-linux", + "s390x-redhat-linux"}; using std::begin; using std::end; diff --git a/clang/lib/Driver/ToolChains/HIPUtility.cpp b/clang/lib/Driver/ToolChains/HIPUtility.cpp index b1ff697b368b135d662ed08e6acd60fe1a264750..f32a23f111e4bf9736b642afc8da4c896383bb67 100644 --- a/clang/lib/Driver/ToolChains/HIPUtility.cpp +++ b/clang/lib/Driver/ToolChains/HIPUtility.cpp @@ -106,9 +106,9 @@ private: std::string ID = IA->getId().str(); if (!ID.empty()) { ID = llvm::utohexstr(llvm::MD5Hash(ID), /*LowerCase=*/true); - FatBinSymbols.insert(Twine(FatBinPrefix + "_" + ID).str()); + FatBinSymbols.insert((FatBinPrefix + Twine('_') + ID).str()); GPUBinHandleSymbols.insert( - Twine(GPUBinHandlePrefix + "_" + ID).str()); + (GPUBinHandlePrefix + Twine('_') + ID).str()); continue; } if (IA->getInputArg().getNumValues() == 0) diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 9cba0c2614eef7b3c10a797ec33551ddeae66377..c015e03fa15e72576a73e8e630026a8df2821c29 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -308,6 +308,7 @@ struct ScalarEnumerationTraits { FormatStyle::EscapedNewlineAlignmentStyle &Value) { IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign); IO.enumCase(Value, "Left", FormatStyle::ENAS_Left); + IO.enumCase(Value, "LeftWithLastLine", FormatStyle::ENAS_LeftWithLastLine); IO.enumCase(Value, "Right", FormatStyle::ENAS_Right); // For backward compatibility. diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp index ed06d6098a9f20ae0b831bbe15fa4914b2f9fccf..50531aee9d597800a933a0a21b94c08a7338cdd1 100644 --- a/clang/lib/Format/WhitespaceManager.cpp +++ b/clang/lib/Format/WhitespaceManager.cpp @@ -1245,22 +1245,29 @@ void WhitespaceManager::alignTrailingComments(unsigned Start, unsigned End, } void WhitespaceManager::alignEscapedNewlines() { - if (Style.AlignEscapedNewlines == FormatStyle::ENAS_DontAlign) + const auto Align = Style.AlignEscapedNewlines; + if (Align == FormatStyle::ENAS_DontAlign) return; - bool AlignLeft = Style.AlignEscapedNewlines == FormatStyle::ENAS_Left; - unsigned MaxEndOfLine = AlignLeft ? 0 : Style.ColumnLimit; + const bool WithLastLine = Align == FormatStyle::ENAS_LeftWithLastLine; + const bool AlignLeft = Align == FormatStyle::ENAS_Left || WithLastLine; + const auto MaxColumn = Style.ColumnLimit; + unsigned MaxEndOfLine = AlignLeft ? 0 : MaxColumn; unsigned StartOfMacro = 0; for (unsigned i = 1, e = Changes.size(); i < e; ++i) { Change &C = Changes[i]; - if (C.NewlinesBefore > 0) { - if (C.ContinuesPPDirective) { - MaxEndOfLine = std::max(C.PreviousEndOfTokenColumn + 2, MaxEndOfLine); - } else { - alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine); - MaxEndOfLine = AlignLeft ? 0 : Style.ColumnLimit; - StartOfMacro = i; - } + if (C.NewlinesBefore == 0 && (!WithLastLine || C.Tok->isNot(tok::eof))) + continue; + const bool InPPDirective = C.ContinuesPPDirective; + const auto BackslashColumn = C.PreviousEndOfTokenColumn + 2; + if (InPPDirective || + (WithLastLine && (MaxColumn == 0 || BackslashColumn <= MaxColumn))) { + MaxEndOfLine = std::max(BackslashColumn, MaxEndOfLine); + } + if (!InPPDirective) { + alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine); + MaxEndOfLine = AlignLeft ? 0 : MaxColumn; + StartOfMacro = i; } } alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine); diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index b20e6efcebfd10fb944e1a1b5961aa681ed7d8aa..683f87e8c8c79e36ed90da00151fc400708f3e87 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -229,12 +229,32 @@ IncrementalCompilerBuilder::CreateCudaHost() { } Interpreter::Interpreter(std::unique_ptr CI, - llvm::Error &Err) { - llvm::ErrorAsOutParameter EAO(&Err); + llvm::Error &ErrOut, + std::unique_ptr JITBuilder) + : JITBuilder(std::move(JITBuilder)) { + llvm::ErrorAsOutParameter EAO(&ErrOut); auto LLVMCtx = std::make_unique(); TSCtx = std::make_unique(std::move(LLVMCtx)); - IncrParser = std::make_unique(*this, std::move(CI), - *TSCtx->getContext(), Err); + IncrParser = std::make_unique( + *this, std::move(CI), *TSCtx->getContext(), ErrOut); + if (ErrOut) + return; + + // Not all frontends support code-generation, e.g. ast-dump actions don't + if (IncrParser->getCodeGen()) { + if (llvm::Error Err = CreateExecutor()) { + ErrOut = joinErrors(std::move(ErrOut), std::move(Err)); + return; + } + + // Process the PTUs that came from initialization. For example -include will + // give us a header that's processed at initialization of the preprocessor. + for (PartialTranslationUnit &PTU : IncrParser->getPTUs()) + if (llvm::Error Err = Execute(PTU)) { + ErrOut = joinErrors(std::move(ErrOut), std::move(Err)); + return; + } + } } Interpreter::~Interpreter() { @@ -382,25 +402,29 @@ createJITTargetMachineBuilder(const std::string &TT) { return llvm::orc::JITTargetMachineBuilder(llvm::Triple(TT)); } -llvm::Expected> -Interpreter::CreateJITBuilder(CompilerInstance &CI) { - auto JTMB = createJITTargetMachineBuilder(CI.getTargetOpts().Triple); - if (!JTMB) - return JTMB.takeError(); - return IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB)); -} - llvm::Error Interpreter::CreateExecutor() { if (IncrExecutor) return llvm::make_error("Operation failed. " "Execution engine exists", std::error_code()); - llvm::Expected> JB = - CreateJITBuilder(*getCompilerInstance()); - if (!JB) - return JB.takeError(); + if (!IncrParser->getCodeGen()) + return llvm::make_error("Operation failed. " + "No code generator available", + std::error_code()); + if (!JITBuilder) { + const std::string &TT = getCompilerInstance()->getTargetOpts().Triple; + auto JTMB = createJITTargetMachineBuilder(TT); + if (!JTMB) + return JTMB.takeError(); + auto JB = IncrementalExecutor::createDefaultJITBuilder(std::move(*JTMB)); + if (!JB) + return JB.takeError(); + JITBuilder = std::move(*JB); + } + llvm::Error Err = llvm::Error::success(); - auto Executor = std::make_unique(*TSCtx, **JB, Err); + auto Executor = + std::make_unique(*TSCtx, *JITBuilder, Err); if (!Err) IncrExecutor = std::move(Executor); diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp index c98645993abe076a4481d0ca837f20c9778ffc9b..c7543a48c0b50e2f2a9ad480298de93138689d9a 100644 --- a/clang/lib/Lex/Lexer.cpp +++ b/clang/lib/Lex/Lexer.cpp @@ -2261,8 +2261,17 @@ bool Lexer::LexRawStringLiteral(Token &Result, const char *CurPtr, unsigned PrefixLen = 0; - while (PrefixLen != 16 && isRawStringDelimBody(CurPtr[PrefixLen])) + while (PrefixLen != 16 && isRawStringDelimBody(CurPtr[PrefixLen])) { ++PrefixLen; + if (!isLexingRawMode() && + llvm::is_contained({'$', '@', '`'}, CurPtr[PrefixLen])) { + const char *Pos = &CurPtr[PrefixLen]; + Diag(Pos, LangOpts.CPlusPlus26 + ? diag::warn_cxx26_compat_raw_string_literal_character_set + : diag::ext_cxx26_raw_string_literal_character_set) + << StringRef(Pos, 1); + } + } // If the last character was not a '(', then we didn't lex a valid delimiter. if (CurPtr[PrefixLen] != '(') { diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 86e8a6b7ee0eddd820b496197c14453cbb6dd0aa..c528917437332756e90101dd917af145de3337d1 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -467,6 +467,11 @@ bool Parser::ParseAttributeArgumentList( break; } + if (Actions.DiagnoseUnexpandedParameterPack(Expr.get())) { + SawError = true; + break; + } + Exprs.push_back(Expr.get()); if (Tok.isNot(tok::comma)) diff --git a/clang/lib/Parse/ParseOpenACC.cpp b/clang/lib/Parse/ParseOpenACC.cpp index e9c60f76165b68077c9e9737a306e83514cefc25..63afc18783a1f7cf652fdacc810d20e1fc863459 100644 --- a/clang/lib/Parse/ParseOpenACC.cpp +++ b/clang/lib/Parse/ParseOpenACC.cpp @@ -1347,11 +1347,13 @@ void Parser::ParseOpenACCCacheVarList() { ParseOpenACCVarList(OpenACCClauseKind::Invalid); } -Parser::OpenACCDirectiveParseInfo Parser::ParseOpenACCDirective() { - SourceLocation StartLoc = getCurToken().getLocation(); +Parser::OpenACCDirectiveParseInfo +Parser::ParseOpenACCDirective() { + SourceLocation StartLoc = ConsumeAnnotationToken(); + SourceLocation DirLoc = getCurToken().getLocation(); OpenACCDirectiveKind DirKind = ParseOpenACCDirectiveKind(*this); - getActions().OpenACC().ActOnConstruct(DirKind, StartLoc); + getActions().OpenACC().ActOnConstruct(DirKind, DirLoc); // Once we've parsed the construct/directive name, some have additional // specifiers that need to be taken care of. Atomic has an 'atomic-clause' @@ -1390,7 +1392,7 @@ Parser::OpenACCDirectiveParseInfo Parser::ParseOpenACCDirective() { break; case OpenACCDirectiveKind::Wait: // OpenACC has an optional paren-wrapped 'wait-argument'. - if (ParseOpenACCWaitArgument(StartLoc, /*IsDirective=*/true).Failed) + if (ParseOpenACCWaitArgument(DirLoc, /*IsDirective=*/true).Failed) T.skipToEnd(); else T.consumeClose(); @@ -1404,7 +1406,8 @@ Parser::OpenACCDirectiveParseInfo Parser::ParseOpenACCDirective() { } // Parses the list of clauses, if present, plus set up return value. - OpenACCDirectiveParseInfo ParseInfo{DirKind, StartLoc, SourceLocation{}, + OpenACCDirectiveParseInfo ParseInfo{DirKind, StartLoc, DirLoc, + SourceLocation{}, ParseOpenACCClauseList(DirKind)}; assert(Tok.is(tok::annot_pragma_openacc_end) && @@ -1421,7 +1424,6 @@ Parser::DeclGroupPtrTy Parser::ParseOpenACCDirectiveDecl() { assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token"); ParsingOpenACCDirectiveRAII DirScope(*this); - ConsumeAnnotationToken(); OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective(); @@ -1438,7 +1440,6 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() { assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token"); ParsingOpenACCDirectiveRAII DirScope(*this); - ConsumeAnnotationToken(); OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective(); if (getActions().OpenACC().ActOnStartStmtDirective(DirInfo.DirKind, @@ -1456,6 +1457,6 @@ StmtResult Parser::ParseOpenACCDirectiveStmt() { } return getActions().OpenACC().ActOnEndStmtDirective( - DirInfo.DirKind, DirInfo.StartLoc, DirInfo.EndLoc, DirInfo.Clauses, - AssocStmt); + DirInfo.DirKind, DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.EndLoc, + DirInfo.Clauses, AssocStmt); } diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index e959dd6378f46b21da506c67633b55d7c128b9fb..cd8df3332724f07176cefd4e7a2d7ccfa0b3f1c5 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -25,7 +25,6 @@ #include "clang/Sema/SemaOpenMP.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/UniqueVector.h" #include "llvm/Frontend/OpenMP/OMPAssume.h" #include "llvm/Frontend/OpenMP/OMPContext.h" #include diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index b0af04451166ca20febe0cf6c1e2b78ef0ce5750..c25203243ee49bccf6f78f68eb5a02f242a0722e 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -239,7 +239,15 @@ Retry: auto IsStmtAttr = [](ParsedAttr &Attr) { return Attr.isStmtAttr(); }; bool AllAttrsAreStmtAttrs = llvm::all_of(CXX11Attrs, IsStmtAttr) && llvm::all_of(GNUAttrs, IsStmtAttr); - if (((GNUAttributeLoc.isValid() && !(HaveAttrs && AllAttrsAreStmtAttrs)) || + // In C, the grammar production for statement (C23 6.8.1p1) does not allow + // for declarations, which is different from C++ (C++23 [stmt.pre]p1). So + // in C++, we always allow a declaration, but in C we need to check whether + // we're in a statement context that allows declarations. e.g., in C, the + // following is invalid: if (1) int x; + if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt || + (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) != + ParsedStmtContext()) && + ((GNUAttributeLoc.isValid() && !(HaveAttrs && AllAttrsAreStmtAttrs)) || isDeclarationStatement())) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; DeclGroupPtrTy Decl; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index fac9a58fa2689d68f1b8fa878e4d9537c7e45fee..c3251f3cc9d81faa2db8ccfc07ac6ed326259ca8 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3824,7 +3824,7 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, const PointerType *pointerType = PointerArg->getType()->getAs(); if (!pointerType) { Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer) - << PointerArg->getType() << PointerArg->getSourceRange(); + << PointerArg->getType() << 0 << PointerArg->getSourceRange(); return true; } @@ -3858,7 +3858,7 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && !ValType->isBlockPointerType() && !ValType->isFloatingType()) { Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intfltptr) - << PointerArg->getType() << PointerArg->getSourceRange(); + << PointerArg->getType() << 0 << PointerArg->getSourceRange(); return true; } @@ -6803,7 +6803,7 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, const PointerType *pointerType = Ptr->getType()->getAs(); if (!pointerType) { Diag(ExprRange.getBegin(), diag::err_atomic_builtin_must_be_pointer) - << Ptr->getType() << Ptr->getSourceRange(); + << Ptr->getType() << 0 << Ptr->getSourceRange(); return ExprError(); } @@ -6832,6 +6832,13 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, } } + // Pointer to object of size zero is not allowed. + if (Context.getTypeInfoInChars(AtomTy).Width.isZero()) { + Diag(ExprRange.getBegin(), diag::err_atomic_builtin_must_be_pointer) + << Ptr->getType() << 1 << Ptr->getSourceRange(); + return ExprError(); + } + // For an arithmetic operation, the implied arithmetic must be well-formed. if (Form == Arithmetic) { // GCC does not enforce these rules for GNU atomics, but we do to help catch @@ -7223,7 +7230,7 @@ ExprResult Sema::BuiltinAtomicOverloaded(ExprResult TheCallResult) { const PointerType *pointerType = FirstArg->getType()->getAs(); if (!pointerType) { Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer) - << FirstArg->getType() << FirstArg->getSourceRange(); + << FirstArg->getType() << 0 << FirstArg->getSourceRange(); return ExprError(); } @@ -7231,7 +7238,7 @@ ExprResult Sema::BuiltinAtomicOverloaded(ExprResult TheCallResult) { if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && !ValType->isBlockPointerType()) { Diag(DRE->getBeginLoc(), diag::err_atomic_builtin_must_be_pointer_intptr) - << FirstArg->getType() << FirstArg->getSourceRange(); + << FirstArg->getType() << 0 << FirstArg->getSourceRange(); return ExprError(); } diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index ad3ca4cc94ca638a34c03b2bfa2b42049d736ac3..cd1c5f9391ccd45baeb85243f5dd7607452adbae 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -5692,8 +5692,15 @@ QualType getApproximateType(const Expr *E) { } } if (const auto *UO = llvm::dyn_cast(E)) { - if (UO->getOpcode() == UnaryOperatorKind::UO_Deref) - return UO->getSubExpr()->getType()->getPointeeType(); + if (UO->getOpcode() == UnaryOperatorKind::UO_Deref) { + // We recurse into the subexpression because it could be of dependent + // type. + if (auto Pointee = getApproximateType(UO->getSubExpr())->getPointeeType(); + !Pointee.isNull()) + return Pointee; + // Our caller expects a non-null result, even though the SubType is + // supposed to have a pointee. Fall through to Unresolved anyway. + } } return Unresolved; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 2a87b26f17a2b1cb0d5b245c52511925e475ce56..e29ddd81a3f8898f79de7d8a60ee51f3c3f61ec8 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -538,8 +538,9 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, } else if (AllowDeducedTemplate) { if (auto *TD = getAsTypeTemplateDecl(IIDecl)) { assert(!FoundUsingShadow || FoundUsingShadow->getTargetDecl() == TD); - TemplateName Template = - FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD); + TemplateName Template = Context.getQualifiedTemplateName( + SS ? SS->getScopeRep() : nullptr, /*TemplateKeyword=*/false, + FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD)); T = Context.getDeducedTemplateSpecializationType(Template, QualType(), false); // Don't wrap in a further UsingType. @@ -1137,12 +1138,10 @@ Corrected: dyn_cast(*Result.begin()); assert(!FoundUsingShadow || TD == cast(FoundUsingShadow->getTargetDecl())); - Template = - FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD); - if (SS.isNotEmpty()) - Template = Context.getQualifiedTemplateName(SS.getScopeRep(), - /*TemplateKeyword=*/false, - Template); + Template = Context.getQualifiedTemplateName( + SS.getScopeRep(), + /*TemplateKeyword=*/false, + FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD)); } else { // All results were non-template functions. This is a function template // name. diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 8ab429e2a136efecbc44c4a565cc1f5773e1856c..631fd4e354927f5cb665281c88d8f4a5739ffcea 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -11547,12 +11547,12 @@ bool Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R, TemplateName SpecifiedName = RetTST.getTypePtr()->getTemplateName(); bool TemplateMatches = Context.hasSameTemplateName(SpecifiedName, GuidedTemplate); - auto TKind = SpecifiedName.getKind(); - // A Using TemplateName can't actually be valid (either it's qualified, or - // we're in the wrong scope). But we have diagnosed these problems - // already. - bool SimplyWritten = TKind == TemplateName::Template || - TKind == TemplateName::UsingTemplate; + + const QualifiedTemplateName *Qualifiers = + SpecifiedName.getAsQualifiedTemplateName(); + assert(Qualifiers && "expected QualifiedTemplate"); + bool SimplyWritten = !Qualifiers->hasTemplateKeyword() && + Qualifiers->getQualifier() == nullptr; if (SimplyWritten && TemplateMatches) AcceptableReturnType = true; else { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ff9c5ead36dcfa64c145d013bd771c750404f336..fb4154757775bc001db9d2a5758e2e344f7f3d9a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3284,10 +3284,10 @@ ExprResult Sema::BuildDeclarationNameExpr( return CreateRecoveryExpr(NameInfo.getBeginLoc(), NameInfo.getEndLoc(), {}); } - if (TemplateDecl *Template = dyn_cast(D)) { + if (TemplateDecl *TD = dyn_cast(D)) { // Specifically diagnose references to class templates that are missing // a template argument list. - diagnoseMissingTemplateArguments(TemplateName(Template), Loc); + diagnoseMissingTemplateArguments(SS, /*TemplateKeyword=*/false, TD, Loc); return ExprError(); } @@ -5506,6 +5506,15 @@ struct EnsureImmediateInvocationInDefaultArgs // cause it to incorrectly point it to the outermost class // in the case of nested struct initialization. ExprResult TransformCXXThisExpr(CXXThisExpr *E) { return E; } + + // Rewrite to source location to refer to the context in which they are used. + ExprResult TransformSourceLocExpr(SourceLocExpr *E) { + if (E->getParentContext() == SemaRef.CurContext) + return E; + return getDerived().RebuildSourceLocExpr(E->getIdentKind(), E->getType(), + E->getBeginLoc(), E->getEndLoc(), + SemaRef.CurContext); + } }; ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, @@ -17223,8 +17232,7 @@ ExprResult Sema::TransformToPotentiallyEvaluated(Expr *E) { TypeSourceInfo *Sema::TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo) { assert(isUnevaluatedContext() && "Should only transform unevaluated expressions"); - ExprEvalContexts.back().Context = - ExprEvalContexts[ExprEvalContexts.size() - 2].Context; + ExprEvalContexts.back().Context = parentEvaluationContext().Context; if (isUnevaluatedContext()) return TInfo; return TransformToPE(*this).TransformType(TInfo); @@ -17241,14 +17249,13 @@ Sema::PushExpressionEvaluationContext( // discarded statements or immediate context are themselves // a discarded statement or an immediate context, respectively. ExprEvalContexts.back().InDiscardedStatement = - ExprEvalContexts[ExprEvalContexts.size() - 2] - .isDiscardedStatementContext(); + parentEvaluationContext().isDiscardedStatementContext(); // C++23 [expr.const]/p15 // An expression or conversion is in an immediate function context if [...] // it is a subexpression of a manifestly constant-evaluated expression or // conversion. - const auto &Prev = ExprEvalContexts[ExprEvalContexts.size() - 2]; + const auto &Prev = parentEvaluationContext(); ExprEvalContexts.back().InImmediateFunctionContext = Prev.isImmediateFunctionContext() || Prev.isConstantEvaluated(); @@ -17693,7 +17700,7 @@ void Sema::PopExpressionEvaluationContext() { // Append the collected materialized temporaries into previous context before // exit if the previous also is a lifetime extending context. - auto &PrevRecord = ExprEvalContexts[ExprEvalContexts.size() - 2]; + auto &PrevRecord = parentEvaluationContext(); if (getLangOpts().CPlusPlus23 && Rec.InLifetimeExtendingContext && PrevRecord.InLifetimeExtendingContext && !Rec.ForRangeLifetimeExtendTemps.empty()) { diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index d3e9dcb4f4399a6365888f0bbdefb5d22a3661e1..6595abbcdda5b11e9c02df395ab077d574a2d33d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1444,10 +1444,10 @@ bool Sema::CheckCXXThisType(SourceLocation Loc, QualType Type) { // category are defined within such member functions as they are within // an implicit object member function). DeclContext *DC = getFunctionLevelDeclContext(); - if (const auto *Method = dyn_cast(DC); - Method && Method->isExplicitObjectMemberFunction()) { + const auto *Method = dyn_cast(DC); + if (Method && Method->isExplicitObjectMemberFunction()) { Diag(Loc, diag::err_invalid_this_use) << 1; - } else if (isLambdaCallWithExplicitObjectParameter(CurContext)) { + } else if (Method && isLambdaCallWithExplicitObjectParameter(CurContext)) { Diag(Loc, diag::err_invalid_this_use) << 1; } else { Diag(Loc, diag::err_invalid_this_use) << 0; diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 9aa60204bf29decff73a69fb0f9a0d5a60efa865..3ae1af26d0096fd54b5714bf7dae1afedfaf6e49 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1194,7 +1194,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, if (VarTemplateDecl *VarTempl = dyn_cast(MemberDecl)) { if (!TemplateArgs) { - diagnoseMissingTemplateArguments(TemplateName(VarTempl), MemberLoc); + diagnoseMissingTemplateArguments( + SS, /*TemplateKeyword=*/TemplateKWLoc.isValid(), VarTempl, MemberLoc); return ExprError(); } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index ef0a655b631ab42fd044f604e66258ecfa81205e..be6ea20a956a393428d46e13be77bd46af6ca37e 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -5897,6 +5897,16 @@ void Sema::diagnoseTypo(const TypoCorrection &Correction, NamedDecl *ChosenDecl = Correction.isKeyword() ? nullptr : Correction.getFoundDecl(); + + // For builtin functions which aren't declared anywhere in source, + // don't emit the "declared here" note. + if (const auto *FD = dyn_cast_if_present(ChosenDecl); + FD && FD->getBuiltinID() && + PrevNote.getDiagID() == diag::note_previous_decl && + Correction.getCorrectionRange().getBegin() == FD->getBeginLoc()) { + ChosenDecl = nullptr; + } + if (PrevNote.getDiagID() && ChosenDecl) Diag(ChosenDecl->getLocation(), PrevNote) << CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo); diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 09d91b31cfe5f9ee00ed8f73ae2edfaffa17c73e..15239f4f35c39fdf4870afd90f8487e4d497319b 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -844,7 +844,7 @@ ExprResult SemaOpenACC::CheckReductionVar(Expr *VarExpr) { } void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K, - SourceLocation StartLoc) { + SourceLocation DirLoc) { switch (K) { case OpenACCDirectiveKind::Invalid: // Nothing to do here, an invalid kind has nothing we can check here. We @@ -859,7 +859,7 @@ void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K, // here as these constructs do not take any arguments. break; default: - Diag(StartLoc, diag::warn_acc_construct_unimplemented) << K; + Diag(DirLoc, diag::warn_acc_construct_unimplemented) << K; break; } } @@ -1265,6 +1265,7 @@ bool SemaOpenACC::ActOnStartStmtDirective(OpenACCDirectiveKind K, StmtResult SemaOpenACC::ActOnEndStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, + SourceLocation DirLoc, SourceLocation EndLoc, ArrayRef Clauses, StmtResult AssocStmt) { @@ -1278,7 +1279,7 @@ StmtResult SemaOpenACC::ActOnEndStmtDirective(OpenACCDirectiveKind K, case OpenACCDirectiveKind::Kernels: // TODO OpenACC: Add clauses to the construct here. return OpenACCComputeConstruct::Create( - getASTContext(), K, StartLoc, EndLoc, Clauses, + getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses, AssocStmt.isUsable() ? AssocStmt.get() : nullptr); } llvm_unreachable("Unhandled case in directive handling?"); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 0c89fca8d38eb4a9951d2ac38260a8f577197a0c..6c5e8afbcfb6eec2d7b51e9be009e1e20bbef4f5 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -13,6 +13,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DependenceFlags.h" @@ -1481,7 +1482,7 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New, } if (OldMethod && NewMethod && !OldMethod->isStatic() && - !OldMethod->isStatic()) { + !NewMethod->isStatic()) { bool HaveCorrespondingObjectParameters = [&](const CXXMethodDecl *Old, const CXXMethodDecl *New) { auto NewObjectType = New->getFunctionObjectParameterReferenceType(); @@ -11301,8 +11302,16 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, Expr *FromExpr = Conv.Bad.FromExpr; QualType FromTy = Conv.Bad.getFromType(); QualType ToTy = Conv.Bad.getToType(); - SourceRange ToParamRange = - !isObjectArgument ? Fn->getParamDecl(I)->getSourceRange() : SourceRange(); + SourceRange ToParamRange; + + // FIXME: In presence of parameter packs we can't determine parameter range + // reliably, as we don't have access to instantiation. + bool HasParamPack = + llvm::any_of(Fn->parameters().take_front(I), [](const ParmVarDecl *Parm) { + return Parm->isParameterPack(); + }); + if (!isObjectArgument && !HasParamPack) + ToParamRange = Fn->getParamDecl(I)->getSourceRange(); if (FromTy == S.Context.OverloadTy) { assert(FromExpr && "overload set argument came from implicit argument?"); @@ -14354,7 +14363,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, if (Fn.isInvalid()) return ExprError(); return CXXOperatorCallExpr::Create(Context, Op, Fn.get(), ArgsArray, - Context.DependentTy, VK, OpLoc, + Context.DependentTy, VK_PRValue, OpLoc, CurFPFeatureOverrides()); } diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index 8735d96c840793d809b5c264b153a868aa987443..6f538ed55cb72e6e929370f7ae1d26c464a7334d 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -285,7 +285,7 @@ bool Sema::CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt, static Attr *handleNoInlineAttr(Sema &S, Stmt *St, const ParsedAttr &A, SourceRange Range) { NoInlineAttr NIA(S.Context, A); - if (!NIA.isClangNoInline()) { + if (!NIA.isStmtNoInline()) { S.Diag(St->getBeginLoc(), diag::warn_function_attribute_ignored_in_stmt) << "[[clang::noinline]]"; return nullptr; @@ -684,10 +684,8 @@ ExprResult Sema::ActOnCXXAssumeAttr(Stmt *St, const ParsedAttr &A, } if (!getLangOpts().CPlusPlus23 && - A.getSyntax() == AttributeCommonInfo::AS_CXX11) { - llvm::dbgs() << "Syntax: " << int(A.getSyntax()) << "\n"; + A.getSyntax() == AttributeCommonInfo::AS_CXX11) Diag(A.getLoc(), diag::ext_cxx23_attr) << A << Range; - } return Assumption; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 39e9dbed0c3e0bc49591e792c35b7d27df8f3b5e..3e3ed77de710e5ac3184b009613feabbb65b7bb8 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -292,7 +292,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S, Template = FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD); assert(!FoundUsingShadow || FoundUsingShadow->getTargetDecl() == TD); - if (SS.isSet() && !SS.isInvalid()) { + if (!SS.isInvalid()) { NestedNameSpecifier *Qualifier = SS.getScopeRep(); Template = Context.getQualifiedTemplateName(Qualifier, hasTemplateKeyword, Template); @@ -342,8 +342,11 @@ bool Sema::isDeductionGuideName(Scope *S, const IdentifierInfo &Name, if (!TD || !getAsTypeTemplateDecl(TD)) return false; - if (Template) - *Template = TemplateTy::make(TemplateName(TD)); + if (Template) { + TemplateName Name = Context.getQualifiedTemplateName( + SS.getScopeRep(), /*TemplateKeyword=*/false, TemplateName(TD)); + *Template = TemplateTy::make(Name); + } return true; } @@ -983,10 +986,6 @@ ParsedTemplateArgument Sema::ActOnTemplateTypeArgument(TypeResult ParsedType) { if (auto DTST = TL.getAs()) { TemplateName Name = DTST.getTypePtr()->getTemplateName(); - if (SS.isSet()) - Name = Context.getQualifiedTemplateName(SS.getScopeRep(), - /*HasTemplateKeyword=*/false, - Name); ParsedTemplateArgument Result(SS, TemplateTy::make(Name), DTST.getTemplateNameLoc()); if (EllipsisLoc.isValid()) @@ -5621,6 +5620,15 @@ void Sema::diagnoseMissingTemplateArguments(TemplateName Name, } } +void Sema::diagnoseMissingTemplateArguments(const CXXScopeSpec &SS, + bool TemplateKeyword, + TemplateDecl *TD, + SourceLocation Loc) { + TemplateName Name = Context.getQualifiedTemplateName( + SS.getScopeRep(), TemplateKeyword, TemplateName(TD)); + diagnoseMissingTemplateArguments(Name, Loc); +} + ExprResult Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, @@ -5691,7 +5699,8 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, // Non-function templates require a template argument list. if (auto *TD = R.getAsSingle()) { if (!TemplateArgs && !isa(TD)) { - diagnoseMissingTemplateArguments(TemplateName(TD), R.getNameLoc()); + diagnoseMissingTemplateArguments( + SS, /*TemplateKeyword=*/TemplateKWLoc.isValid(), TD, R.getNameLoc()); return ExprError(); } } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index f9ec34163e656b08d59ce86aa334dbbf7018eeeb..440b8bc60eaab6adf913a9ca427f1ae12e0df14e 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -589,7 +589,6 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, // arguments as defaults. if (auto *TempArg = dyn_cast_or_null( Arg.getAsTemplateDecl())) { - assert(Arg.getKind() == TemplateName::Template); assert(!TempArg->isExpandedParameterPack()); TemplateParameterList *As = TempArg->getTemplateParameters(); @@ -658,6 +657,18 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, /// \returns the result of template argument deduction so far. Note that a /// "success" result means that template argument deduction has not yet failed, /// but it may still fail, later, for other reasons. + +static const TemplateSpecializationType *getLastTemplateSpecType(QualType QT) { + for (const Type *T = QT.getTypePtr(); /**/; /**/) { + const TemplateSpecializationType *TST = + T->getAs(); + assert(TST && "Expected a TemplateSpecializationType"); + if (!TST->isSugared()) + return TST; + T = TST->desugar().getTypePtr(); + } +} + static TemplateDeductionResult DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams, const QualType P, QualType A, @@ -666,26 +677,35 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams, QualType UP = P; if (const auto *IP = P->getAs()) UP = IP->getInjectedSpecializationType(); - // FIXME: Try to preserve type sugar here, which is hard - // because of the unresolved template arguments. - const auto *TP = UP.getCanonicalType()->castAs(); + + assert(isa(UP.getCanonicalType())); + const TemplateSpecializationType *TP = ::getLastTemplateSpecType(UP); TemplateName TNP = TP->getTemplateName(); // If the parameter is an alias template, there is nothing to deduce. if (const auto *TD = TNP.getAsTemplateDecl(); TD && TD->isTypeAlias()) return TemplateDeductionResult::Success; - ArrayRef PResolved = TP->template_arguments(); + // FIXME: To preserve sugar, the TST needs to carry sugared resolved + // arguments. + ArrayRef PResolved = + TP->getCanonicalTypeInternal() + ->castAs() + ->template_arguments(); QualType UA = A; + std::optional NNS; // Treat an injected-class-name as its underlying template-id. - if (const auto *Injected = A->getAs()) + if (const auto *Elaborated = A->getAs()) { + NNS = Elaborated->getQualifier(); + } else if (const auto *Injected = A->getAs()) { UA = Injected->getInjectedSpecializationType(); + NNS = nullptr; + } // Check whether the template argument is a dependent template-id. - // FIXME: Should not lose sugar here. - if (const auto *SA = - dyn_cast(UA.getCanonicalType())) { + if (isa(UA.getCanonicalType())) { + const TemplateSpecializationType *SA = ::getLastTemplateSpecType(UA); TemplateName TNA = SA->getTemplateName(); // If the argument is an alias template, there is nothing to deduce. @@ -698,11 +718,19 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams, SA->template_arguments(), Deduced); Result != TemplateDeductionResult::Success) return Result; + + // FIXME: To preserve sugar, the TST needs to carry sugared resolved + // arguments. + ArrayRef AResolved = + SA->getCanonicalTypeInternal() + ->castAs() + ->template_arguments(); + // Perform template argument deduction on each template // argument. Ignore any missing/extra arguments, since they could be // filled in by default arguments. - return DeduceTemplateArguments(S, TemplateParams, PResolved, - SA->template_arguments(), Info, Deduced, + return DeduceTemplateArguments(S, TemplateParams, PResolved, AResolved, + Info, Deduced, /*NumberOfArgumentsMustMatch=*/false); } @@ -718,11 +746,15 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams, return TemplateDeductionResult::NonDeducedMismatch; } + TemplateName TNA = TemplateName(SA->getSpecializedTemplate()); + if (NNS) + TNA = S.Context.getQualifiedTemplateName( + *NNS, false, TemplateName(SA->getSpecializedTemplate())); + // Perform template argument deduction for the template name. - if (auto Result = DeduceTemplateArguments( - S, TemplateParams, TP->getTemplateName(), - TemplateName(SA->getSpecializedTemplate()), Info, - SA->getTemplateArgs().asArray(), Deduced); + if (auto Result = + DeduceTemplateArguments(S, TemplateParams, TNP, TNA, Info, + SA->getTemplateArgs().asArray(), Deduced); Result != TemplateDeductionResult::Success) return Result; diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 0b20604665068c77065564612e14df79b4b20843..7a44b978aacdb7351aa2fbb3cfc4146c6f87a0b1 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -66,6 +66,9 @@ namespace { bool shouldWalkTypesOfTypeLocs() const { return false; } + // We need this so we can find e.g. attributes on lambdas. + bool shouldVisitImplicitCode() const { return true; } + //------------------------------------------------------------------------ // Recording occurrences of (unexpanded) parameter packs. //------------------------------------------------------------------------ diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index ef0b6b701a52c58401284dc9237a5856ba311ce6..7cec82c7010280a73477cd97b6aafaab2b2677a0 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -6005,12 +6005,16 @@ namespace { DeclarationNameInfo DNI = DeclarationNameInfo( TL.getTypePtr()->getTypeConstraintConcept()->getDeclName(), TemplateId->TemplateNameLoc); - auto TN = TemplateId->Template.get(); + + NamedDecl *FoundDecl; + if (auto TN = TemplateId->Template.get(); + UsingShadowDecl *USD = TN.getAsUsingShadowDecl()) + FoundDecl = cast(USD); + else + FoundDecl = cast_if_present(TN.getAsTemplateDecl()); + auto *CR = ConceptReference::Create( - Context, NNS, TemplateId->TemplateKWLoc, DNI, - /*FoundDecl=*/TN.getKind() == TemplateName::NameKind::UsingTemplate - ? cast(TN.getAsUsingShadowDecl()) - : cast_if_present(TN.getAsTemplateDecl()), + Context, NNS, TemplateId->TemplateKWLoc, DNI, FoundDecl, /*NamedDecl=*/TL.getTypePtr()->getTypeConstraintConcept(), ASTTemplateArgumentListInfo::Create(Context, TemplateArgsInfo)); TL.setConceptReference(CR); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index dee335b526991b4413cbcb07f759f6c4b653da9f..efba99b85b0fb19d7ba6c12adce8aa34aad14a37 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4033,11 +4033,12 @@ public: StmtResult RebuildOpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation BeginLoc, + SourceLocation DirLoc, SourceLocation EndLoc, ArrayRef Clauses, StmtResult StrBlock) { - return getSema().OpenACC().ActOnEndStmtDirective(K, BeginLoc, EndLoc, - Clauses, StrBlock); + return getSema().OpenACC().ActOnEndStmtDirective(K, BeginLoc, DirLoc, + EndLoc, Clauses, StrBlock); } private: @@ -4604,6 +4605,7 @@ TreeTransform::TransformTemplateName(CXXScopeSpec &SS, ObjectType, AllowInjectedClassName); } + // FIXME: Try to preserve more of the TemplateName. if (TemplateDecl *Template = Name.getAsTemplateDecl()) { TemplateDecl *TransTemplate = cast_or_null(getDerived().TransformDecl(NameLoc, @@ -4611,11 +4613,8 @@ TreeTransform::TransformTemplateName(CXXScopeSpec &SS, if (!TransTemplate) return TemplateName(); - if (!getDerived().AlwaysRebuild() && - TransTemplate == Template) - return Name; - - return TemplateName(TransTemplate); + return getDerived().RebuildTemplateName(SS, /*TemplateKeyword=*/false, + TransTemplate); } if (SubstTemplateTemplateParmPackStorage *SubstPack @@ -11559,8 +11558,8 @@ StmtResult TreeTransform::TransformOpenACCComputeConstruct( getSema().OpenACC().ActOnAssociatedStmt(C->getDirectiveKind(), StrBlock); return getDerived().RebuildOpenACCComputeConstruct( - C->getDirectiveKind(), C->getBeginLoc(), C->getEndLoc(), - TransformedClauses, StrBlock); + C->getDirectiveKind(), C->getBeginLoc(), C->getDirectiveLoc(), + C->getEndLoc(), TransformedClauses, StrBlock); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index d7fc6697eaf74c41aec86d6ceb3d3e382126e60a..4a6e1d23161be35925533ccfe98d3dd1ef811e8f 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -1264,7 +1264,7 @@ bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M, if (!Lex.first) { Lex = std::make_pair( &M, llvm::ArrayRef( - reinterpret_cast(Blob.data()), + reinterpret_cast(Blob.data()), Blob.size() / sizeof(DeclID))); } DC->setHasExternalLexicalStorage(true); @@ -3401,7 +3401,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, case TU_UPDATE_LEXICAL: { DeclContext *TU = ContextObj->getTranslationUnitDecl(); LexicalContents Contents( - reinterpret_cast(Blob.data()), + reinterpret_cast(Blob.data()), static_cast(Blob.size() / sizeof(DeclID))); TULexicalDecls.push_back(std::make_pair(&F, Contents)); TU->setHasExternalLexicalStorage(true); @@ -4059,7 +4059,7 @@ void ASTReader::ReadModuleOffsetMap(ModuleFile &F) const { RemapBuilder DeclRemap(F.DeclRemap); RemapBuilder TypeRemap(F.TypeRemap); - auto &ImportedModuleVector = F.DependentModules; + auto &ImportedModuleVector = F.TransitiveImports; assert(ImportedModuleVector.empty()); while (Data < DataEnd) { diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index eac4faff285490b09b6f307bd02c2c578351bddb..bea2b94989107071879be807cc3b4a94e67b255a 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2797,6 +2797,7 @@ void ASTStmtReader::VisitOpenACCConstructStmt(OpenACCConstructStmt *S) { (void)Record.readInt(); S->Kind = Record.readEnum(); S->Range = Record.readSourceRange(); + S->DirectiveLoc = Record.readSourceLocation(); Record.readOpenACCClauseList(S->Clauses); } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 00b0e48083217c2c8bfc4042f6959b5659fae0d5..e830c4026ea78fa54bb8677bede73d6bf7fd97e3 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1049,6 +1049,7 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(DECL_UNRESOLVED_USING_VALUE); RECORD(DECL_UNRESOLVED_USING_TYPENAME); RECORD(DECL_LINKAGE_SPEC); + RECORD(DECL_EXPORT); RECORD(DECL_CXX_RECORD); RECORD(DECL_CXX_METHOD); RECORD(DECL_CXX_CONSTRUCTOR); @@ -5037,6 +5038,14 @@ void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) { continue; } + // If we're writing C++ named modules, don't emit declarations which are + // not from modules by default. They may be built in declarations (be + // handled above) or implcit declarations (see the implementation of + // `Sema::Initialize()` for example). + if (isWritingStdCXXNamedModules() && !D->getOwningModule() && + D->isImplicit()) + continue; + GetDeclRef(D); } @@ -6197,8 +6206,9 @@ bool ASTWriter::wasDeclEmitted(const Decl *D) const { return true; bool Emitted = DeclIDs.contains(D); - assert((Emitted || GeneratingReducedBMI) && - "The declaration can only be omitted in reduced BMI."); + assert((Emitted || (!D->getOwningModule() && isWritingStdCXXNamedModules()) || + GeneratingReducedBMI) && + "The declaration within modules can only be omitted in reduced BMI."); return Emitted; } @@ -7825,7 +7835,7 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { case OpenACCClauseKind::If: { const auto *IC = cast(C); writeSourceLocation(IC->getLParenLoc()); - writeStmtRef(IC->getConditionExpr()); + AddStmt(const_cast(IC->getConditionExpr())); return; } case OpenACCClauseKind::Self: { @@ -7833,7 +7843,7 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { writeSourceLocation(SC->getLParenLoc()); writeBool(SC->hasConditionExpr()); if (SC->hasConditionExpr()) - writeStmtRef(SC->getConditionExpr()); + AddStmt(const_cast(SC->getConditionExpr())); return; } case OpenACCClauseKind::NumGangs: { @@ -7847,13 +7857,13 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { case OpenACCClauseKind::NumWorkers: { const auto *NWC = cast(C); writeSourceLocation(NWC->getLParenLoc()); - writeStmtRef(NWC->getIntExpr()); + AddStmt(const_cast(NWC->getIntExpr())); return; } case OpenACCClauseKind::VectorLength: { const auto *NWC = cast(C); writeSourceLocation(NWC->getLParenLoc()); - writeStmtRef(NWC->getIntExpr()); + AddStmt(const_cast(NWC->getIntExpr())); return; } case OpenACCClauseKind::Private: { @@ -7932,15 +7942,15 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) { writeSourceLocation(AC->getLParenLoc()); writeBool(AC->hasIntExpr()); if (AC->hasIntExpr()) - writeStmtRef(AC->getIntExpr()); + AddStmt(const_cast(AC->getIntExpr())); return; } case OpenACCClauseKind::Wait: { const auto *WC = cast(C); writeSourceLocation(WC->getLParenLoc()); writeBool(WC->getDevNumExpr()); - if (const Expr *DNE = WC->getDevNumExpr()) - writeStmtRef(DNE); + if (Expr *DNE = WC->getDevNumExpr()) + AddStmt(DNE); writeSourceLocation(WC->getQueuesLoc()); writeOpenACCIntExprList(WC->getQueueIdExprs()); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index a44852af97bea3e54f66c97860b8364322c2adb7..3c586b270fbf4f6c46df9ccb85f09682f2dcdd37 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2847,6 +2847,7 @@ void ASTStmtWriter::VisitOpenACCConstructStmt(OpenACCConstructStmt *S) { Record.push_back(S->clauses().size()); Record.writeEnum(S->Kind); Record.AddSourceRange(S->Range); + Record.AddSourceLocation(S->DirectiveLoc); Record.writeOpenACCClauseList(S->clauses()); } diff --git a/clang/lib/StaticAnalyzer/Checkers/PutenvStackArrayChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PutenvStackArrayChecker.cpp index d59cebf0aa5cb17c514e3d071e9e1717bf169679..bf81d57bf82fd34eea733059672b129237ffaa91 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PutenvStackArrayChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PutenvStackArrayChecker.cpp @@ -44,9 +44,14 @@ void PutenvStackArrayChecker::checkPostCall(const CallEvent &Call, SVal ArgV = Call.getArgSVal(0); const Expr *ArgExpr = Call.getArgExpr(0); - const MemSpaceRegion *MSR = ArgV.getAsRegion()->getMemorySpace(); - if (!isa(MSR)) + const auto *SSR = + dyn_cast(ArgV.getAsRegion()->getMemorySpace()); + if (!SSR) + return; + const auto *StackFrameFuncD = + dyn_cast_or_null(SSR->getStackFrame()->getDecl()); + if (StackFrameFuncD && StackFrameFuncD->isMain()) return; StringRef ErrorMsg = "The 'putenv' function should not be called with " diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp index 26879f2f87c8beac1b222a3211ad0605b869f2da..9df108e28ecdbb6cf200963e1e9cc20fdcd26f67 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp @@ -58,7 +58,7 @@ public: std::optional HasSpecializedDelete(CXXMethodDecl *Decl) { if (auto *Body = Decl->getBody()) return VisitBody(Body); - if (auto *Tmpl = Decl->getTemplateInstantiationPattern()) + if (Decl->getTemplateInstantiationPattern()) return std::nullopt; // Indeterminate. There was no concrete instance. return false; } diff --git a/clang/test/AST/Interp/functions.cpp b/clang/test/AST/Interp/functions.cpp index e95ade8ef51b701574f6397eda91b3de83d79c53..10c62a43ef33b459fdcc100a95ae1b4e02ccdb0c 100644 --- a/clang/test/AST/Interp/functions.cpp +++ b/clang/test/AST/Interp/functions.cpp @@ -623,3 +623,9 @@ namespace FuncPtrParam { *a; // both-warning {{expression result unused}} } } + +namespace { + void f() noexcept; + void (&r)() = f; + void (&cond3)() = r; +} diff --git a/clang/test/AST/Interp/objc.mm b/clang/test/AST/Interp/objc.mm index 44b74d193b66a75be19686ccd8ae833606baefdf..6402c8ae098fdbb0112508bf6d0c487bbc0b6d6a 100644 --- a/clang/test/AST/Interp/objc.mm +++ b/clang/test/AST/Interp/objc.mm @@ -6,3 +6,8 @@ static_assert(a, ""); // both-error {{static assertion expression is not an integral constant expression}} } @end + +@interface NSString +@end +constexpr NSString *t0 = @"abc"; +constexpr NSString *t1 = @("abc"); diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp index 97ac3e916955534b7bf04dc48f70763d0519bb8a..0a89c81bafd578808b7cb25cad134900e7f1708a 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -1467,3 +1467,16 @@ namespace IgnoredCtorWithZeroInit { return (S(), true); } } + +#if __cplusplus >= 202002L +namespace VirtOperator { + /// This used to crash because it's a virtual CXXOperatorCallExpr. + struct B { + virtual constexpr bool operator==(const B&) const { return true; } + }; + struct D : B { + constexpr bool operator==(const B&) const override{ return false; } // both-note {{operator}} + }; + constexpr bool cmp_base_derived = D() == D(); // both-warning {{ambiguous}} +} +#endif diff --git a/clang/test/AST/ast-dump-ctad-alias.cpp b/clang/test/AST/ast-dump-ctad-alias.cpp index 9382558393e4c0eeae744c98a1d9433cf4f98d27..08a3be5c6b754e472a1722847fd664c4c23da9e5 100644 --- a/clang/test/AST/ast-dump-ctad-alias.cpp +++ b/clang/test/AST/ast-dump-ctad-alias.cpp @@ -29,17 +29,17 @@ Out2::AInner t(1.0); // CHECK: | `-FunctionTemplateDecl {{.*}} // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 Y // CHECK-NEXT: | |-BinaryOperator {{.*}} '' '&&' -// CHECK-NEXT: | | |-UnresolvedLookupExpr {{.*}} '' lvalue (no ADL) = 'Concept' +// CHECK-NEXT: | | |-UnresolvedLookupExpr {{.*}} '' lvalue (no ADL) = 'Concept' // CHECK-NEXT: | | | |-TemplateArgument type 'int' // CHECK-NEXT: | | | | `-BuiltinType {{.*}} 'int' // CHECK-NEXT: | | | `-TemplateArgument type 'type-parameter-1-0' // CHECK-NEXT: | | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0 // CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_deducible -// CHECK-NEXT: | | |-DeducedTemplateSpecializationType {{.*}} 'AInner' dependent +// CHECK-NEXT: | | |-DeducedTemplateSpecializationType {{.*}} 'Out2::AInner' dependent // CHECK-NEXT: | | `-ElaboratedType {{.*}} 'Inner' sugar dependent // CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner' dependent Inner // CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-1-0' -// CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'type-parameter-1-0' +// CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'type-parameter-1-0' // CHECK-NEXT: | | |-FunctionTemplate {{.*}} '' // CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0 // CHECK-NEXT: | |-CXXDeductionGuideDecl {{.*}} 'auto (type-parameter-0-0) -> Inner' diff --git a/clang/test/AST/ast-dump-decl.cpp b/clang/test/AST/ast-dump-decl.cpp index e062d4f068a403a876cd72ffced8012b424dc291..e84241cee922f5938b5b8f2abaeb2abeaeca4a8f 100644 --- a/clang/test/AST/ast-dump-decl.cpp +++ b/clang/test/AST/ast-dump-decl.cpp @@ -459,21 +459,23 @@ namespace testClassTemplateDecl { // CHECK: ClassTemplateDecl 0x{{.+}} <{{.+}}:[[@LINE-148]]:3, col:31> col:31 TestTemplateDefaultNonType{{$}} // CHECK-NEXT: |-NonTypeTemplateParmDecl 0x{{.+}} col:16 'int' depth 0 index 0 I{{$}} -// CHECK-NEXT: | `-TemplateArgument expr{{$}} +// CHECK-NEXT: | `-TemplateArgument expr '42'{{$}} // CHECK-NEXT: | `-IntegerLiteral 0x{{.+}} 'int' 42{{$}} // CHECK-NEXT: `-CXXRecordDecl 0x{{.+}} col:31 struct TestTemplateDefaultNonType{{$}} // CHECK: ClassTemplateDecl 0x{{.+}} <{{.+}}:{{.*}}:3, col:68> col:68 TestTemplateTemplateDefaultType{{$}} // CHECK-NEXT: |-TemplateTemplateParmDecl 0x{{.+}} col:37 depth 0 index 0 TT{{$}} // CHECK-NEXT: | |-TemplateTypeParmDecl 0x{{.+}} col:29 typename depth 1 index 0{{$}} -// CHECK-NEXT: | `-TemplateArgument template TestClassTemplate{{$}} -// CHECK-NEXT: `-CXXRecordDecl 0x{{.+}} col:68 struct TestTemplateTemplateDefaultType{{$}} +// CHECK-NEXT: | `-TemplateArgument template 'TestClassTemplate':'testClassTemplateDecl::TestClassTemplate' qualified{{$}} +// CHECK-NEXT: | `-ClassTemplateDecl 0x{{.+}} line:{{.+}}:30 TestClassTemplate{{$}} +// CHECK-NEXT: `-CXXRecordDecl 0x{{.+}} col:68 struct TestTemplateTemplateDefaultType{{$}} // CHECK: ClassTemplateDecl 0x{{.+}} prev 0x{{.+}} <{{.+}}:{{.*}}:3, col:82> col:48 TestTemplateTemplateDefaultType{{$}} // CHECK-NEXT: |-TemplateTemplateParmDecl 0x{{.+}} col:37 depth 0 index 0 TT{{$}} // CHECK-NEXT: | |-TemplateTypeParmDecl 0x{{.+}} col:29 typename depth 1 index 0{{$}} -// CHECK-NEXT: | `-TemplateArgument template TestClassTemplate{{$}} -// CHECK-NEXT: | `-inherited from TemplateTemplateParm 0x{{.+}} 'TT'{{$}} +// CHECK-NEXT: | `-TemplateArgument template 'TestClassTemplate':'testClassTemplateDecl::TestClassTemplate' qualified{{$}} +// CHECK-NEXT: | |-inherited from TemplateTemplateParm 0x{{.+}} 'TT'{{$}} +// CHECK-NEXT: | `-ClassTemplateDecl 0x{{.+}} line:{{.+}}:30 TestClassTemplate // CHECK-NEXT: `-CXXRecordDecl 0x{{.+}} prev 0x{{.+}} col:48 struct TestTemplateTemplateDefaultType definition{{$}} // CHECK-NEXT: |-DefinitionData empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init{{$}} // CHECK-NEXT: | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr{{$}} @@ -683,7 +685,8 @@ namespace TestTemplateTemplateParmDecl { // CHECK: FunctionTemplateDecl // CHECK-NEXT: TemplateTemplateParmDecl{{.*}} T // CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename -// CHECK-NEXT: TemplateArgument{{.*}} template A +// CHECK-NEXT: TemplateArgument{{.*}} template 'A':'TestTemplateTemplateParmDecl::A' qualified{{$}} +// CHECK-NEXT: ClassTemplateDecl {{.*}} A // CHECK-NEXT: TemplateTemplateParmDecl{{.*}} ... U // CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename @@ -710,12 +713,12 @@ namespace TestTemplateArgument { template class testIntegral { }; template class testIntegral<1>; // CHECK: ClassTemplateSpecializationDecl{{.*}} class testIntegral - // CHECK: TemplateArgument{{.*}} integral 1 + // CHECK: TemplateArgument{{.*}} integral '1' template class> class testTemplate { }; template class testTemplate; // CHECK: ClassTemplateSpecializationDecl{{.*}} class testTemplate - // CHECK: TemplateArgument{{.*}} A + // CHECK: TemplateArgument{{.*}} 'TestTemplateArgument::A'{{$}} template class ...T> class C { B testTemplateExpansion; @@ -731,10 +734,10 @@ namespace TestTemplateArgument { template class testPack { }; template class testPack<0, 1, 2>; // CHECK: ClassTemplateSpecializationDecl{{.*}} class testPack - // CHECK: TemplateArgument{{.*}} integral 0 + // CHECK: TemplateArgument{{.*}} integral '0' // CHECK-NEXT: TemplateArgument{{.*}} pack - // CHECK-NEXT: TemplateArgument{{.*}} integral 1 - // CHECK-NEXT: TemplateArgument{{.*}} integral 2 + // CHECK-NEXT: TemplateArgument{{.*}} integral '1' + // CHECK-NEXT: TemplateArgument{{.*}} integral '2' } namespace testUsingDecl { diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp index f9e9ee9d35dde6989b5c0a43b80640f2fe029143..5da025c229ea3d80adf606514f75f132f81bff2f 100644 --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -233,7 +233,7 @@ void PostfixExpressions(S a, S *p, U *r) { r->template U::~U(); // CHECK: CXXMemberCallExpr 0x{{[^ ]*}} 'void' // CHECK-NEXT: MemberExpr 0x{{[^ ]*}} '' ->~U 0x{{[^ ]*}} - // CHECK-NEXT: NestedNameSpecifier TypeSpecWithTemplate 'U' + // CHECK-NEXT: NestedNameSpecifier TypeSpecWithTemplate 'template U':'U' // CHECK-NEXT: ImplicitCastExpr // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} 'U *' lvalue ParmVar 0x{{[^ ]*}} 'r' 'U *' diff --git a/clang/test/AST/ast-dump-openmp-begin-declare-variant_template_2.cpp b/clang/test/AST/ast-dump-openmp-begin-declare-variant_template_2.cpp index da46cef7f3f1bce8b43f3aeaf0df8a7535f4f1a9..6fe05e33a5fb871058561bc5881457ba3e3d6fcb 100644 --- a/clang/test/AST/ast-dump-openmp-begin-declare-variant_template_2.cpp +++ b/clang/test/AST/ast-dump-openmp-begin-declare-variant_template_2.cpp @@ -79,7 +79,7 @@ int test() { // CHECK-NEXT: | | `-ReturnStmt [[ADDR_22:0x[a-z0-9]*]] // CHECK-NEXT: | | `-IntegerLiteral [[ADDR_23:0x[a-z0-9]*]] 'int' 0 // CHECK-NEXT: | `-FunctionDecl [[ADDR_24:0x[a-z0-9]*]] line:9:5 used also_before_mismatch 'int ({{.*}})' -// CHECK-NEXT: | |-TemplateArgument integral 0 +// CHECK-NEXT: | |-TemplateArgument integral '0' // CHECK-NEXT: | `-CompoundStmt [[ADDR_25:0x[a-z0-9]*]] // CHECK-NEXT: | `-ReturnStmt [[ADDR_26:0x[a-z0-9]*]] // CHECK-NEXT: | `-IntegerLiteral [[ADDR_23]] 'int' 0 @@ -179,7 +179,7 @@ int test() { // CHECK-NEXT: | | `-OMPDeclareVariantAttr [[ADDR_101:0x[a-z0-9]*]] <> Implicit implementation={extension(allow_templates)} // CHECK-NEXT: | | `-DeclRefExpr [[ADDR_102:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_103:0x[a-z0-9]*]] 'only_def[implementation={extension(allow_templates)}]' 'int ({{.*}})' // CHECK-NEXT: | `-FunctionDecl [[ADDR_104:0x[a-z0-9]*]] col:5 used only_def 'int ({{.*}})' -// CHECK-NEXT: | |-TemplateArgument integral 0 +// CHECK-NEXT: | |-TemplateArgument integral '0' // CHECK-NEXT: | `-OMPDeclareVariantAttr [[ADDR_105:0x[a-z0-9]*]] <> Implicit implementation={extension(allow_templates)} // CHECK-NEXT: | `-DeclRefExpr [[ADDR_106:0x[a-z0-9]*]] 'int ({{.*}})' {{.*}}Function [[ADDR_107:0x[a-z0-9]*]] 'only_def[implementation={extension(allow_templates)}]' 'int ({{.*}})' // CHECK-NEXT: |-FunctionTemplateDecl [[ADDR_108:0x[a-z0-9]*]] line:38:1 only_def[implementation={extension(allow_templates)}] @@ -189,7 +189,7 @@ int test() { // CHECK-NEXT: | | `-ReturnStmt [[ADDR_110:0x[a-z0-9]*]] // CHECK-NEXT: | | `-IntegerLiteral [[ADDR_111:0x[a-z0-9]*]] 'int' 0 // CHECK-NEXT: | `-FunctionDecl [[ADDR_107]] line:38:1 only_def[implementation={extension(allow_templates)}] 'int ({{.*}})' -// CHECK-NEXT: | |-TemplateArgument integral 0 +// CHECK-NEXT: | |-TemplateArgument integral '0' // CHECK-NEXT: | `-CompoundStmt [[ADDR_112:0x[a-z0-9]*]] // CHECK-NEXT: | `-ReturnStmt [[ADDR_113:0x[a-z0-9]*]] // CHECK-NEXT: | `-IntegerLiteral [[ADDR_111]] 'int' 0 diff --git a/clang/test/AST/ast-dump-template-decls.cpp b/clang/test/AST/ast-dump-template-decls.cpp index 37f6d8a0472d30e6ca37b6f79a9518fca24021bc..55bded4c77d4ba8acf878d356053f660142db537 100644 --- a/clang/test/AST/ast-dump-template-decls.cpp +++ b/clang/test/AST/ast-dump-template-decls.cpp @@ -116,7 +116,7 @@ template struct C { using type2 = typename C::type1; // CHECK: TypeAliasDecl 0x{{[^ ]*}} col:7 type2 'typename C::type1':'void (int)' // CHECK-NEXT: ElaboratedType 0x{{[^ ]*}} 'typename C::type1' sugar -// CHECK-NEXT: TemplateSpecializationType 0x{{[^ ]*}} 'type1' sugar alias type1 +// CHECK-NEXT: TemplateSpecializationType 0x{{[^ ]*}} 'type1' sugar alias C::type1 // CHECK-NEXT: TemplateArgument type 'void' // CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void' // CHECK-NEXT: FunctionProtoType 0x{{[^ ]*}} 'void (int)' cdecl @@ -149,7 +149,7 @@ template struct D { template using B = int(int (*...p)(T, U)); }; using t2 = D::B; -// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'B' sugar alias B +// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'B' sugar alias D::B{{$}} // CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl // CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl // CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1 @@ -169,7 +169,7 @@ template> class D1, class D2> using D = D1 class E {}; using test1 = D; -// CHECK: TypeAliasDecl 0x{{[^ ]*}} col:7 test1 'D':'subst_default_argument::E>' +// CHECK: TypeAliasDecl 0x{{[^ ]*}} col:7 test1 'D':'subst_default_argument::E>' // CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'A' sugar A // CHECK-NEXT: |-TemplateArgument type 'int' // CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 1 D2 diff --git a/clang/test/AST/ast-dump-template-name.cpp b/clang/test/AST/ast-dump-template-name.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7972e9f9e9b0655f197819c65e82b78fe6f9916a --- /dev/null +++ b/clang/test/AST/ast-dump-template-name.cpp @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -std=c++26 -ast-dump -ast-dump-filter=Test %s | FileCheck %s + +template