From fcfa2dd517ec1a6045a81e8247e346d630a22618 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Wed, 20 Jun 2018 21:16:37 +0000 Subject: [PATCH 01/11] Add python tool to dump and construct header maps Header maps are binary files used by Xcode, which are used to map header names or paths to other locations. Clang has support for those since its inception, but there's not a lot of header map testing around. Since it's a binary format, testing becomes pretty much brittle and its hard to even know what's inside if you don't have the appropriate tools. Add a python based tool that allows creating and dumping header maps based on a json description of those. While here, rewrite tests to use the tool and remove the binary files from the tree. This tool was initially written by Daniel Dunbar. Differential Revision: https://reviews.llvm.org/D46485 rdar://problem/39994722 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335177 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 1 + test/CMakeLists.txt | 1 + test/Modules/crash-vfs-headermaps.m | 10 +- .../Inputs/headermap-rel/foo.hmap | Bin 804 -> 0 bytes .../Inputs/headermap-rel/foo.hmap.json | 6 + .../headermap-rel2/project-headers.hmap | Bin 108 -> 0 bytes .../headermap-rel2/project-headers.hmap.json | 6 + .../Inputs/nonportable-hmaps/foo.hmap | Bin 102 -> 0 bytes .../Inputs/nonportable-hmaps/foo.hmap.json | 6 + test/Preprocessor/headermap-rel.c | 8 +- test/Preprocessor/headermap-rel2.c | 9 +- .../nonportable-include-with-hmap.c | 4 +- utils/hmaptool/CMakeLists.txt | 16 + utils/hmaptool/hmaptool | 296 ++++++++++++++++++ 14 files changed, 344 insertions(+), 19 deletions(-) delete mode 100644 test/Preprocessor/Inputs/headermap-rel/foo.hmap create mode 100644 test/Preprocessor/Inputs/headermap-rel/foo.hmap.json delete mode 100644 test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap create mode 100644 test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap.json delete mode 100644 test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap create mode 100644 test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json create mode 100644 utils/hmaptool/CMakeLists.txt create mode 100755 utils/hmaptool/hmaptool diff --git a/CMakeLists.txt b/CMakeLists.txt index ab81ec34b00d..ae8835d751c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -753,6 +753,7 @@ endif() if (LLVM_ADD_NATIVE_VISUALIZERS_TO_SOLUTION) add_subdirectory(utils/ClangVisualizers) endif() +add_subdirectory(utils/hmaptool) configure_file( ${CLANG_SOURCE_DIR}/include/clang/Config/config.h.cmake diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8efe3600c540..8d6db5348e08 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -54,6 +54,7 @@ list(APPEND CLANG_TEST_DEPS clang-rename clang-refactor clang-diff + hmaptool ) if(CLANG_ENABLE_STATIC_ANALYZER) diff --git a/test/Modules/crash-vfs-headermaps.m b/test/Modules/crash-vfs-headermaps.m index 4f88f3ba1197..d33534602800 100644 --- a/test/Modules/crash-vfs-headermaps.m +++ b/test/Modules/crash-vfs-headermaps.m @@ -1,15 +1,9 @@ // REQUIRES: crash-recovery, shell, system-darwin -// This uses a headermap with this entry: -// Foo.h -> Foo/Foo.h - -// Copy out the headermap from test/Preprocessor/Inputs/headermap-rel and avoid -// adding another binary format to the repository. - // RUN: rm -rf %t -// RUN: mkdir -p %t/m -// RUN: cp -a %S/../Preprocessor/Inputs/headermap-rel %t/i +// RUN: mkdir -p %t/m %t/i/Foo.framework/Headers // RUN: echo '// Foo.h' > %t/i/Foo.framework/Headers/Foo.h +// RUN: hmaptool write %S/../Preprocessor/Inputs/headermap-rel/foo.hmap.json %t/i/foo.hmap // RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \ // RUN: %clang -fsyntax-only -fmodules -fmodules-cache-path=%t/m %s \ diff --git a/test/Preprocessor/Inputs/headermap-rel/foo.hmap b/test/Preprocessor/Inputs/headermap-rel/foo.hmap deleted file mode 100644 index 783c64e67bb80a38f23845ed54fac43e2dc101a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 804 ycmXR&%*|kAU|^77W?%r(4nWKa#KRSU{KyW(AbJ#xh5*hGaLdov%U}SK`V0V(7zHB$ diff --git a/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json b/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json new file mode 100644 index 000000000000..ccfd911f0f7f --- /dev/null +++ b/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json @@ -0,0 +1,6 @@ +{ + "mappings" : + { + "Foo.h" : "Foo/Foo.h" + } +} diff --git a/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap b/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap deleted file mode 100644 index a0770fb251242a3eec33dda98beab4f3d38adef8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108 zcmXR&%*|kAU|{e7Vi3&DdU3;?O;17dNI;^O?=)Qr@`l++@<42FQB{FKt<5`9!r E0L3N_r2qf` diff --git a/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap.json b/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap.json new file mode 100644 index 000000000000..e03703b1bb06 --- /dev/null +++ b/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap.json @@ -0,0 +1,6 @@ +{ + "mappings" : + { + "someheader.h" : "Product/someheader.h" + } +} diff --git a/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap b/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap deleted file mode 100644 index 9036f208711c4c0b8f0fc89c58648c63658b863f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102 zcmXR&%*|kAU|{e7Vi3&&#DYMK3_#-CKrDeQh|YG)&({ZHy$pto)Wnq3qGJ6tpa=s* F2moPe3vU1b diff --git a/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json b/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json new file mode 100644 index 000000000000..c69f1df77253 --- /dev/null +++ b/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json @@ -0,0 +1,6 @@ +{ + "mappings" : + { + "Foo/Foo.h" : "headers/foo/Foo.h" + } +} diff --git a/test/Preprocessor/headermap-rel.c b/test/Preprocessor/headermap-rel.c index 38500a70f697..91f0d957e5a6 100644 --- a/test/Preprocessor/headermap-rel.c +++ b/test/Preprocessor/headermap-rel.c @@ -1,8 +1,6 @@ - -// This uses a headermap with this entry: -// Foo.h -> Foo/Foo.h - -// RUN: %clang_cc1 -E %s -o %t.i -I %S/Inputs/headermap-rel/foo.hmap -F %S/Inputs/headermap-rel +// RUN: rm -f %t.hmap +// RUN: hmaptool write %S/Inputs/headermap-rel/foo.hmap.json %t.hmap +// RUN: %clang_cc1 -E %s -o %t.i -I %t.hmap -F %S/Inputs/headermap-rel // RUN: FileCheck %s -input-file %t.i // CHECK: Foo.h is parsed diff --git a/test/Preprocessor/headermap-rel2.c b/test/Preprocessor/headermap-rel2.c index d61f3385b22d..172821efa425 100644 --- a/test/Preprocessor/headermap-rel2.c +++ b/test/Preprocessor/headermap-rel2.c @@ -1,8 +1,7 @@ -// This uses a headermap with this entry: -// someheader.h -> Product/someheader.h - -// RUN: %clang_cc1 -v -fsyntax-only %s -iquote %S/Inputs/headermap-rel2/project-headers.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H -// RUN: %clang_cc1 -fsyntax-only %s -iquote %S/Inputs/headermap-rel2/project-headers.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out +// RUN: rm -f %t.hmap +// RUN: hmaptool write %S/Inputs/headermap-rel2/project-headers.hmap.json %t.hmap +// RUN: %clang_cc1 -v -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H +// RUN: %clang_cc1 -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out // RUN: FileCheck %s -input-file %t.out // CHECK: Product/someheader.h diff --git a/test/Preprocessor/nonportable-include-with-hmap.c b/test/Preprocessor/nonportable-include-with-hmap.c index fc958e7e5e3f..0190d13498a2 100644 --- a/test/Preprocessor/nonportable-include-with-hmap.c +++ b/test/Preprocessor/nonportable-include-with-hmap.c @@ -1,5 +1,7 @@ +// RUN: rm -f %t.hmap +// RUN: hmaptool write %S/Inputs/nonportable-hmaps/foo.hmap.json %t.hmap // RUN: %clang_cc1 -Eonly \ -// RUN: -I%S/Inputs/nonportable-hmaps/foo.hmap \ +// RUN: -I%t.hmap \ // RUN: -I%S/Inputs/nonportable-hmaps \ // RUN: %s -verify // diff --git a/utils/hmaptool/CMakeLists.txt b/utils/hmaptool/CMakeLists.txt new file mode 100644 index 000000000000..f5cc7d856a40 --- /dev/null +++ b/utils/hmaptool/CMakeLists.txt @@ -0,0 +1,16 @@ +set(CLANG_HMAPTOOL hmaptool) + +add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL} + COMMAND ${CMAKE_COMMAND} -E make_directory + ${CMAKE_BINARY_DIR}/bin + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL} + ${CMAKE_BINARY_DIR}/bin/ + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL}) + +list(APPEND Depends ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL}) +install(PROGRAMS ${CLANG_HMAPTOOL} DESTINATION bin) + +add_custom_target(hmaptool ALL DEPENDS ${Depends}) +set_target_properties(hmaptool PROPERTIES FOLDER "Utils") + diff --git a/utils/hmaptool/hmaptool b/utils/hmaptool/hmaptool new file mode 100755 index 000000000000..2b1ca7436c3f --- /dev/null +++ b/utils/hmaptool/hmaptool @@ -0,0 +1,296 @@ +#!/usr/bin/env python +from __future__ import print_function + +import json +import optparse +import os +import struct +import sys + +### + +k_header_magic_LE = 'pamh' +k_header_magic_BE = 'hmap' + +def hmap_hash(str): + """hash(str) -> int + + Apply the "well-known" headermap hash function. + """ + + return sum((ord(c.lower()) * 13 + for c in str), 0) + +class HeaderMap(object): + @staticmethod + def frompath(path): + with open(path, 'rb') as f: + magic = f.read(4) + if magic == k_header_magic_LE: + endian_code = '<' + elif magic == k_header_magic_BE: + endian_code = '>' + else: + raise SystemExit("error: %s: not a headermap" % ( + path,)) + + # Read the header information. + header_fmt = endian_code + 'HHIIII' + header_size = struct.calcsize(header_fmt) + data = f.read(header_size) + if len(data) != header_size: + raise SystemExit("error: %s: truncated headermap header" % ( + path,)) + + (version, reserved, strtable_offset, num_entries, + num_buckets, max_value_len) = struct.unpack(header_fmt, data) + + if version != 1: + raise SystemExit("error: %s: unknown headermap version: %r" % ( + path, version)) + if reserved != 0: + raise SystemExit("error: %s: invalid reserved value in header" % ( + path,)) + + # The number of buckets must be a power of two. + if num_buckets == 0 or (num_buckets & num_buckets - 1) != 0: + raise SystemExit("error: %s: invalid number of buckets" % ( + path,)) + + # Read all of the buckets. + bucket_fmt = endian_code + 'III' + bucket_size = struct.calcsize(bucket_fmt) + buckets_data = f.read(num_buckets * bucket_size) + if len(buckets_data) != num_buckets * bucket_size: + raise SystemExit("error: %s: truncated headermap buckets" % ( + path,)) + buckets = [struct.unpack(bucket_fmt, + buckets_data[i*bucket_size:(i+1)*bucket_size]) + for i in range(num_buckets)] + + # Read the string table; the format doesn't explicitly communicate the + # size of the string table (which is dumb), so assume it is the rest of + # the file. + f.seek(0, 2) + strtable_size = f.tell() - strtable_offset + f.seek(strtable_offset) + + if strtable_size == 0: + raise SystemExit("error: %s: unable to read zero-sized string table"%( + path,)) + strtable = f.read(strtable_size) + + if len(strtable) != strtable_size: + raise SystemExit("error: %s: unable to read complete string table"%( + path,)) + if strtable[-1] != '\0': + raise SystemExit("error: %s: invalid string table in headermap" % ( + path,)) + + return HeaderMap(num_entries, buckets, strtable) + + def __init__(self, num_entries, buckets, strtable): + self.num_entries = num_entries + self.buckets = buckets + self.strtable = strtable + + def get_string(self, idx): + if idx >= len(self.strtable): + raise SystemExit("error: %s: invalid string index" % ( + path,)) + end_idx = self.strtable.index('\0', idx) + return self.strtable[idx:end_idx] + + @property + def mappings(self): + for key_idx,prefix_idx,suffix_idx in self.buckets: + if key_idx == 0: + continue + yield (self.get_string(key_idx), + self.get_string(prefix_idx) + self.get_string(suffix_idx)) + +### + +def action_dump(name, args): + "dump a headermap file" + + parser = optparse.OptionParser("%%prog %s [options] " % ( + name,)) + parser.add_option("-v", "--verbose", dest="verbose", + help="show more verbose output [%default]", + action="store_true", default=False) + (opts, args) = parser.parse_args(args) + + if len(args) != 1: + parser.error("invalid number of arguments") + + path, = args + + hmap = HeaderMap.frompath(path) + + # Dump all of the buckets. + print ('Header Map: %s' % (path,)) + if opts.verbose: + print ('headermap: %r' % (path,)) + print (' num entries: %d' % (hmap.num_entries,)) + print (' num buckets: %d' % (len(hmap.buckets),)) + print (' string table size: %d' % (len(hmap.strtable),)) + for i,bucket in enumerate(hmap.buckets): + key_idx,prefix_idx,suffix_idx = bucket + + if key_idx == 0: + continue + + # Get the strings. + key = hmap.get_string(key_idx) + prefix = hmap.get_string(prefix_idx) + suffix = hmap.get_string(suffix_idx) + + print (" bucket[%d]: %r -> (%r, %r) -- %d" % ( + i, key, prefix, suffix, (hmap_hash(key) & (num_buckets - 1)))) + else: + mappings = sorted(hmap.mappings) + for key,value in mappings: + print ("%s -> %s" % (key, value)) + print () + +def next_power_of_two(value): + if value < 0: + raise ArgumentError + return 1 if value == 0 else 2**(value - 1).bit_length() + +def action_write(name, args): + "write a headermap file from a JSON definition" + + parser = optparse.OptionParser("%%prog %s [options] " % ( + name,)) + (opts, args) = parser.parse_args(args) + + if len(args) != 2: + parser.error("invalid number of arguments") + + input_path,output_path = args + + with open(input_path, "r") as f: + input_data = json.load(f) + + # Compute the headermap contents, we make a table that is 1/3 full. + mappings = input_data['mappings'] + num_buckets = next_power_of_two(len(mappings) * 3) + + table = [(0, 0, 0) + for i in range(num_buckets)] + max_value_len = 0 + strtable = "\0" + for key,value in mappings.items(): + if not isinstance(key, str): + key = key.decode('utf-8') + if not isinstance(value, str): + value = value.decode('utf-8') + max_value_len = max(max_value_len, len(value)) + + key_idx = len(strtable) + strtable += key + '\0' + prefix = os.path.dirname(value) + '/' + suffix = os.path.basename(value) + prefix_idx = len(strtable) + strtable += prefix + '\0' + suffix_idx = len(strtable) + strtable += suffix + '\0' + + hash = hmap_hash(key) + for i in range(num_buckets): + idx = (hash + i) % num_buckets + if table[idx][0] == 0: + table[idx] = (key_idx, prefix_idx, suffix_idx) + break + else: + raise RuntimeError + + endian_code = '<' + magic = k_header_magic_LE + magic_size = 4 + header_fmt = endian_code + 'HHIIII' + header_size = struct.calcsize(header_fmt) + bucket_fmt = endian_code + 'III' + bucket_size = struct.calcsize(bucket_fmt) + strtable_offset = magic_size + header_size + num_buckets * bucket_size + header = (1, 0, strtable_offset, len(mappings), + num_buckets, max_value_len) + + # Write out the headermap. + with open(output_path, 'wb') as f: + f.write(magic.encode()) + f.write(struct.pack(header_fmt, *header)) + for bucket in table: + f.write(struct.pack(bucket_fmt, *bucket)) + f.write(strtable.encode()) + +def action_tovfs(name, args): + "convert a headermap to a VFS layout" + + parser = optparse.OptionParser("%%prog %s [options] " % ( + name,)) + parser.add_option("", "--build-path", dest="build_path", + help="build path prefix", + action="store", type=str) + (opts, args) = parser.parse_args(args) + + if len(args) != 2: + parser.error("invalid number of arguments") + if opts.build_path is None: + parser.error("--build-path is required") + + input_path,output_path = args + + hmap = HeaderMap.frompath(input_path) + + # Create the table for all the objects. + vfs = {} + vfs['version'] = 0 + build_dir_contents = [] + vfs['roots'] = [{ + 'name' : opts.build_path, + 'type' : 'directory', + 'contents' : build_dir_contents }] + + # We assume we are mapping framework paths, so a key of "Foo/Bar.h" maps to + # "/Foo.framework/Headers/Bar.h". + for key,value in hmap.mappings: + # If this isn't a framework style mapping, ignore it. + components = key.split('/') + if len(components) != 2: + continue + framework_name,header_name = components + build_dir_contents.append({ + 'name' : '%s.framework/Headers/%s' % (framework_name, + header_name), + 'type' : 'file', + 'external-contents' : value }) + + with open(output_path, 'w') as f: + json.dump(vfs, f, indent=2) + +commands = dict((name[7:].replace("_","-"), f) + for name,f in locals().items() + if name.startswith('action_')) + +def usage(): + print ("Usage: %s command [options]" % ( + os.path.basename(sys.argv[0])), file=sys.stderr) + print (file=sys.stderr) + print ("Available commands:", file=sys.stderr) + cmds_width = max(map(len, commands)) + for name,func in sorted(commands.items()): + print (" %-*s - %s" % (cmds_width, name, func.__doc__), file=sys.stderr) + sys.exit(1) + +def main(): + if len(sys.argv) < 2 or sys.argv[1] not in commands: + usage() + + cmd = sys.argv[1] + commands[cmd](cmd, sys.argv[2:]) + +if __name__ == '__main__': + main() From 39990b1e95721caf4dbe0cee68a46552f7f03dd1 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 20 Jun 2018 21:58:20 +0000 Subject: [PATCH 02/11] Related to PR37768: improve diagnostics for class name shadowing. Diagnose the name of the class being shadowed by using declarations, and improve the diagnostics for the case where the name of the class is shadowed by a non-static data member in a class with constructors. In the latter case, we now always give the "member with the same name as its class" diagnostic regardless of the relative order of the member and the constructor, rather than giving an inscrutible diagnostic if the constructor appears second. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335182 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Sema/Sema.h | 3 ++ lib/Parse/ParseDecl.cpp | 14 ++++---- lib/Parse/ParseExprCXX.cpp | 16 ++++----- lib/Sema/SemaDeclCXX.cpp | 58 +++++++++++++++++++++++--------- lib/Sema/SemaExprCXX.cpp | 33 ++++++++++++++++++ test/CXX/class/class.mem/p13.cpp | 47 ++++++++++++++++++++++++++ test/CXX/class/class.mem/p14.cpp | 5 ++- test/CXX/drs/dr0xx.cpp | 5 ++- 8 files changed, 143 insertions(+), 38 deletions(-) diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 76418143199c..8b4cf02fdeb7 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -4984,6 +4984,8 @@ class Sema { SourceLocation NameLoc, IdentifierInfo &Name); + ParsedType getConstructorName(IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, CXXScopeSpec &SS); ParsedType getDestructorName(SourceLocation TildeLoc, IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec &SS, @@ -5704,6 +5706,7 @@ class Sema { //===--------------------------------------------------------------------===// // C++ Classes // + CXXRecordDecl *getCurrentClass(Scope *S, const CXXScopeSpec *SS); bool isCurrentClassName(const IdentifierInfo &II, Scope *S, const CXXScopeSpec *SS = nullptr); bool isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 83bfd46d8931..e3691565480b 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3250,6 +3250,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, continue; } + // If we're in a context where the identifier could be a class name, + // check whether this is a constructor declaration. + if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class && + Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) && + isConstructorDeclarator(/*Unqualified*/true)) + goto DoneWithDeclSpec; + ParsedType TypeRep = Actions.getTypeName( *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), nullptr, false, false, nullptr, false, false, @@ -3269,13 +3276,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, goto DoneWithDeclSpec; } - // If we're in a context where the identifier could be a class name, - // check whether this is a constructor declaration. - if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class && - Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) && - isConstructorDeclarator(/*Unqualified*/true)) - goto DoneWithDeclSpec; - // Likewise, if this is a context where the identifier could be a template // name, check whether this is a deduction guide declaration. if (getLangOpts().CPlusPlus17 && diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index ad91ff00210b..26b8a0f7793f 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -2505,10 +2505,9 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, if (AllowConstructorName && Actions.isCurrentClassName(*Id, getCurScope(), &SS)) { // We have parsed a constructor name. - ParsedType Ty = Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, false, - false, nullptr, - /*IsCtorOrDtorName=*/true, - /*NonTrivialTypeSourceInfo=*/true); + ParsedType Ty = Actions.getConstructorName(*Id, IdLoc, getCurScope(), SS); + if (!Ty) + return true; Result.setConstructorName(Ty, IdLoc, IdLoc); } else if (getLangOpts().CPlusPlus17 && AllowDeductionGuide && SS.isEmpty() && @@ -2555,11 +2554,10 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, << TemplateId->Name << FixItHint::CreateRemoval( SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)); - ParsedType Ty = - Actions.getTypeName(*TemplateId->Name, TemplateId->TemplateNameLoc, - getCurScope(), &SS, false, false, nullptr, - /*IsCtorOrDtorName=*/true, - /*NontrivialTypeSourceInfo=*/true); + ParsedType Ty = Actions.getConstructorName( + *TemplateId->Name, TemplateId->TemplateNameLoc, getCurScope(), SS); + if (!Ty) + return true; Result.setConstructorName(Ty, TemplateId->TemplateNameLoc, TemplateId->RAngleLoc); ConsumeAnnotationToken(); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 7a7e0378cfdc..f397949964b7 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2059,24 +2059,36 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { return true; } +/// Get the class that is directly named by the current context. This is the +/// class for which an unqualified-id in this scope could name a constructor +/// or destructor. +/// +/// If the scope specifier denotes a class, this will be that class. +/// If the scope specifier is empty, this will be the class whose +/// member-specification we are currently within. Otherwise, there +/// is no such class. +CXXRecordDecl *Sema::getCurrentClass(Scope *, const CXXScopeSpec *SS) { + assert(getLangOpts().CPlusPlus && "No class names in C!"); + + if (SS && SS->isInvalid()) + return nullptr; + + if (SS && SS->isNotEmpty()) { + DeclContext *DC = computeDeclContext(*SS, true); + return dyn_cast_or_null(DC); + } + + return dyn_cast_or_null(CurContext); +} + /// isCurrentClassName - Determine whether the identifier II is the /// name of the class type currently being defined. In the case of /// nested classes, this will only return true if II is the name of /// the innermost class. -bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *, +bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *S, const CXXScopeSpec *SS) { - assert(getLangOpts().CPlusPlus && "No class names in C!"); - - CXXRecordDecl *CurDecl; - if (SS && SS->isSet() && !SS->isInvalid()) { - DeclContext *DC = computeDeclContext(*SS, true); - CurDecl = dyn_cast_or_null(DC); - } else - CurDecl = dyn_cast_or_null(CurContext); - - if (CurDecl && CurDecl->getIdentifier()) - return &II == CurDecl->getIdentifier(); - return false; + CXXRecordDecl *CurDecl = getCurrentClass(S, SS); + return CurDecl && &II == CurDecl->getIdentifier(); } /// Determine whether the identifier II is a typo for the name of @@ -5991,10 +6003,11 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { DeclContext::lookup_result R = Record->lookup(Record->getDeclName()); for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { - NamedDecl *D = *I; - if ((isa(D) && Record->hasUserDeclaredConstructor()) || + NamedDecl *D = (*I)->getUnderlyingDecl(); + if (((isa(D) || isa(D)) && + Record->hasUserDeclaredConstructor()) || isa(D)) { - Diag(D->getLocation(), diag::err_member_name_of_class) + Diag((*I)->getLocation(), diag::err_member_name_of_class) << D->getDeclName(); break; } @@ -9538,6 +9551,19 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, if (isa(D) || isa(D)) continue; + if (auto *RD = dyn_cast(D)) { + // C++ [class.mem]p19: + // If T is the name of a class, then [every named member other than + // a non-static data member] shall have a name different from T + if (RD->isInjectedClassName() && !isa(Target) && + !isa(Target) && + !isa(Target) && + DiagnoseClassNameShadow( + CurContext, + DeclarationNameInfo(Using->getDeclName(), Using->getLocation()))) + return true; + } + if (IsEquivalentForUsingDecl(Context, D, Target)) { if (UsingShadowDecl *Shadow = dyn_cast(*I)) PrevShadow = Shadow; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 5d1001dc84d9..d977ea345388 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -80,6 +80,39 @@ ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS, Context.getTrivialTypeSourceInfo(Type, NameLoc)); } +ParsedType Sema::getConstructorName(IdentifierInfo &II, + SourceLocation NameLoc, + Scope *S, CXXScopeSpec &SS) { + CXXRecordDecl *CurClass = getCurrentClass(S, &SS); + assert(CurClass && &II == CurClass->getIdentifier() && + "not a constructor name"); + + if (SS.isNotEmpty() && RequireCompleteDeclContext(SS, CurClass)) + return ParsedType(); + + // Find the injected-class-name declaration. Note that we make no attempt to + // diagnose cases where the injected-class-name is shadowed: the only + // declaration that can validly shadow the injected-class-name is a + // non-static data member, and if the class contains both a non-static data + // member and a constructor then it is ill-formed (we check that in + // CheckCompletedCXXClass). + CXXRecordDecl *InjectedClassName = nullptr; + for (NamedDecl *ND : CurClass->lookup(&II)) { + auto *RD = dyn_cast(ND); + if (RD && RD->isInjectedClassName()) { + InjectedClassName = RD; + break; + } + } + assert(InjectedClassName && "couldn't find injected class name"); + + QualType T = Context.getTypeDeclType(InjectedClassName); + DiagnoseUseOfDecl(InjectedClassName, NameLoc); + MarkAnyDeclReferenced(NameLoc, InjectedClassName, /*OdrUse=*/false); + + return ParsedType::make(T); +} + ParsedType Sema::getDestructorName(SourceLocation TildeLoc, IdentifierInfo &II, SourceLocation NameLoc, diff --git a/test/CXX/class/class.mem/p13.cpp b/test/CXX/class/class.mem/p13.cpp index bc01fd4d30c5..1b1c0c7f8fc3 100644 --- a/test/CXX/class/class.mem/p13.cpp +++ b/test/CXX/class/class.mem/p13.cpp @@ -67,3 +67,50 @@ struct X4 { // expected-note{{previous}} }; }; }; + +// This includes such things inherited from base classes. +struct B { + static int D0; + int Da() {}; + enum D1 {}; + struct D1a; + typedef int D2; + using D2a = int; + template struct D2b; + template void D2c(); + template static int D2d; + template using D2e = int; + union { int D4; }; + int Dtemplate; + int Dtemplate_with_ctors; +}; +struct B2 { int Dtemplate(); }; + +struct D0 : B { using B::D0; }; // expected-error {{member 'D0' has the same name as its class}} +struct Da : B { using B::Da; }; // expected-error {{member 'Da' has the same name as its class}} +struct D1 : B { using B::D1; }; // expected-error {{member 'D1' has the same name as its class}} +struct D1a : B { using B::D1a; }; // expected-error {{member 'D1a' has the same name as its class}} +struct D2 : B { using B::D2; }; // expected-error {{member 'D2' has the same name as its class}} +struct D2a : B { using B::D2a; }; // expected-error {{member 'D2a' has the same name as its class}} +struct D2b : B { using B::D2b; }; // expected-error {{member 'D2b' has the same name as its class}} +struct D2c : B { using B::D2c; }; // expected-error {{member 'D2c' has the same name as its class}} +struct D2d : B { using B::D2d; }; // expected-error {{member 'D2d' has the same name as its class}} +struct D2e : B { using B::D2e; }; // expected-error {{member 'D2e' has the same name as its class}} +struct D4 : B { using B::D4; }; // expected-error {{member 'D4' has the same name as its class}} + +template struct Dtemplate : B { + using B::Dtemplate; // expected-error {{member 'Dtemplate' has the same name as its class}} +}; +Dtemplate ok; +Dtemplate error; // expected-note {{in instantiation of}} + +template struct Dtemplate_with_ctors : B { + Dtemplate_with_ctors(); + using B::Dtemplate_with_ctors; // expected-error {{member 'Dtemplate_with_ctors' has the same name as its class}} +}; + +template struct CtorDtorName : B { + using B::CtorDtorName; // expected-error {{member 'CtorDtorName' has the same name as its class}} + CtorDtorName(); + ~CtorDtorName(); // expected-error {{expected the class name after '~' to name a destructor}} +}; diff --git a/test/CXX/class/class.mem/p14.cpp b/test/CXX/class/class.mem/p14.cpp index 3f14099ef896..a2f60618565d 100644 --- a/test/CXX/class/class.mem/p14.cpp +++ b/test/CXX/class/class.mem/p14.cpp @@ -9,9 +9,8 @@ struct X0 { }; struct X1 { - int X1; // expected-note{{hidden by a non-type declaration of 'X1' here}} - X1(); // expected-error{{must use 'struct' tag to refer to type 'X1' in this scope}} \ - // expected-error{{expected member name or ';' after declaration specifiers}} + int X1; // expected-error{{member 'X1' has the same name as its class}} + X1(); }; struct X2 { diff --git a/test/CXX/drs/dr0xx.cpp b/test/CXX/drs/dr0xx.cpp index a311d8f33932..048187814db6 100644 --- a/test/CXX/drs/dr0xx.cpp +++ b/test/CXX/drs/dr0xx.cpp @@ -911,9 +911,8 @@ namespace dr80 { // dr80: yes static int B; // expected-error {{same name as its class}} }; struct C { - int C; // expected-note {{hidden by}} - // FIXME: These diagnostics aren't very good. - C(); // expected-error {{must use 'struct' tag to refer to}} expected-error {{expected member name}} + int C; // expected-error {{same name as its class}} + C(); }; struct D { D(); From 9b5ff2db7e31c4bb11a7d468260b068b41c7c285 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Wed, 20 Jun 2018 22:11:59 +0000 Subject: [PATCH 03/11] Warning for framework headers using double quote includes Introduce -Wquoted-include-in-framework-header, which should fire a warning whenever a quote include appears in a framework header and suggest a fix-it. For instance, for header A.h added in the tests, this is how the warning looks like: ./A.framework/Headers/A.h:2:10: warning: double-quoted include "A0.h" in framework header, expected angle-bracketed instead [-Wquoted-include-in-framework-header] #include "A0.h" ^~~~~~ ./A.framework/Headers/A.h:3:10: warning: double-quoted include "B.h" in framework header, expected angle-bracketed instead [-Wquoted-include-in-framework-header] #include "B.h" ^~~~~ This helps users to prevent frameworks from using local headers when in fact they should be targetting system level ones. The warning is off by default. Differential Revision: https://reviews.llvm.org/D47157 rdar://problem/37077034 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335184 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticGroups.td | 1 + include/clang/Basic/DiagnosticLexKinds.td | 5 ++ lib/Lex/HeaderSearch.cpp | 65 ++++++++++++++++++- .../double-quotes/A.framework/Headers/A.h | 6 ++ .../double-quotes/A.framework/Headers/A0.h | 1 + .../A.framework/Modules/module.modulemap | 5 ++ test/Modules/Inputs/double-quotes/B.h | 1 + .../double-quotes/X.framework/Headers/X.h | 1 + .../X.framework/Modules/module.modulemap | 4 ++ test/Modules/Inputs/double-quotes/a.hmap.json | 6 ++ .../Inputs/double-quotes/flat-header-path/Z.h | 1 + .../flat-header-path/Z.modulemap | 4 ++ test/Modules/Inputs/double-quotes/x.hmap.json | 7 ++ test/Modules/Inputs/double-quotes/z.yaml | 28 ++++++++ test/Modules/double-quotes.m | 39 +++++++++++ 15 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 test/Modules/Inputs/double-quotes/A.framework/Headers/A.h create mode 100644 test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h create mode 100644 test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap create mode 100644 test/Modules/Inputs/double-quotes/B.h create mode 100644 test/Modules/Inputs/double-quotes/X.framework/Headers/X.h create mode 100644 test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap create mode 100644 test/Modules/Inputs/double-quotes/a.hmap.json create mode 100644 test/Modules/Inputs/double-quotes/flat-header-path/Z.h create mode 100644 test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap create mode 100644 test/Modules/Inputs/double-quotes/x.hmap.json create mode 100644 test/Modules/Inputs/double-quotes/z.yaml create mode 100644 test/Modules/double-quotes.m diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 643c178743ba..7cc9967738cf 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -31,6 +31,7 @@ def AutoDisableVptrSanitizer : DiagGroup<"auto-disable-vptr-sanitizer">; def Availability : DiagGroup<"availability">; def Section : DiagGroup<"section">; def AutoImport : DiagGroup<"auto-import">; +def FrameworkHdrQuotedInclude : DiagGroup<"quoted-include-in-framework-header">; def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">; def CXXPre14CompatBinaryLiteral : DiagGroup<"c++98-c++11-compat-binary-literal">; def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 9b7f7e677755..de6bffcdcaaa 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -714,6 +714,11 @@ def warn_mmap_redundant_export_as : Warning< def err_mmap_submodule_export_as : Error< "only top-level modules can be re-exported as public">; +def warn_quoted_include_in_framework_header : Warning< + "double-quoted include \"%0\" in framework header, " + "expected angle-bracketed instead" + >, InGroup, DefaultIgnore; + def warn_auto_module_import : Warning< "treating #%select{include|import|include_next|__include_macros}0 as an " "import of module '%1'">, InGroup, DefaultIgnore; diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 1f2c339ea3c9..757cd097e4e5 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -621,6 +621,59 @@ static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) { return CopyStr; } +static bool isFrameworkStylePath(StringRef Path, + SmallVectorImpl &FrameworkName) { + using namespace llvm::sys; + path::const_iterator I = path::begin(Path); + path::const_iterator E = path::end(Path); + + // Detect different types of framework style paths: + // + // ...Foo.framework/{Headers,PrivateHeaders} + // ...Foo.framework/Versions/{A,Current}/{Headers,PrivateHeaders} + // ...Foo.framework/Frameworks/Nested.framework/{Headers,PrivateHeaders} + // ... + // + // and some other variations among these lines. + int FoundComp = 0; + while (I != E) { + if (I->endswith(".framework")) { + FrameworkName.append(I->begin(), I->end()); + ++FoundComp; + } + if (*I == "Headers" || *I == "PrivateHeaders") + ++FoundComp; + ++I; + } + + return FoundComp >= 2; +} + +static void +diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc, + StringRef Includer, StringRef IncludeFilename, + const FileEntry *IncludeFE, bool isAngled = false, + bool FoundByHeaderMap = false) { + SmallString<128> FromFramework, ToFramework; + if (!isFrameworkStylePath(Includer, FromFramework)) + return; + bool IsIncludeeInFramework = + isFrameworkStylePath(IncludeFE->getName(), ToFramework); + + if (!isAngled && !FoundByHeaderMap) { + SmallString<128> NewInclude("<"); + if (IsIncludeeInFramework) { + NewInclude += StringRef(ToFramework).drop_back(10); // drop .framework + NewInclude += "/"; + } + NewInclude += IncludeFilename; + NewInclude += ">"; + Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header) + << IncludeFilename + << FixItHint::CreateReplacement(IncludeLoc, NewInclude); + } +} + /// LookupFile - Given a "foo" or \ reference, look up the indicated file, /// return null on failure. isAngled indicates whether the file reference is /// for system \#include's or not (i.e. using <> instead of ""). Includers, if @@ -722,8 +775,12 @@ const FileEntry *HeaderSearch::LookupFile( RelativePath->clear(); RelativePath->append(Filename.begin(), Filename.end()); } - if (First) + if (First) { + diagnoseFrameworkInclude(Diags, IncludeLoc, + IncluderAndDir.second->getName(), Filename, + FE); return FE; + } // Otherwise, we found the path via MSVC header search rules. If // -Wmsvc-include is enabled, we have to keep searching to see if we @@ -834,6 +891,12 @@ const FileEntry *HeaderSearch::LookupFile( return MSFE; } + bool FoundByHeaderMap = !IsMapped ? false : *IsMapped; + if (!Includers.empty()) + diagnoseFrameworkInclude(Diags, IncludeLoc, + Includers.front().second->getName(), Filename, + FE, isAngled, FoundByHeaderMap); + // Remember this location for the next lookup we do. CacheLookup.HitIdx = i; return FE; diff --git a/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h b/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h new file mode 100644 index 000000000000..17ceb83bb9ca --- /dev/null +++ b/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h @@ -0,0 +1,6 @@ +#include "A0.h" +#include "B.h" + +#include "X.h" + +int foo(); diff --git a/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h b/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h new file mode 100644 index 000000000000..79c6b8893ba4 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h @@ -0,0 +1 @@ +// double-quotes/A.framework/Headers/A0.h diff --git a/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap b/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap new file mode 100644 index 000000000000..09a887a8f489 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap @@ -0,0 +1,5 @@ +// double-quotes/A.framework/Modules/module.modulemap +framework module A { + header "A.h" + header "A0.h" +} diff --git a/test/Modules/Inputs/double-quotes/B.h b/test/Modules/Inputs/double-quotes/B.h new file mode 100644 index 000000000000..724faaef807d --- /dev/null +++ b/test/Modules/Inputs/double-quotes/B.h @@ -0,0 +1 @@ +// double-quotes/B.h diff --git a/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h b/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h new file mode 100644 index 000000000000..0185751299c7 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h @@ -0,0 +1 @@ +// double-quotes/X.framework/Headers/X.h diff --git a/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap b/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap new file mode 100644 index 000000000000..95524704c683 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap @@ -0,0 +1,4 @@ +// double-quotes/X.framework/Modules/module.modulemap +framework module X { + header "X.h" +} diff --git a/test/Modules/Inputs/double-quotes/a.hmap.json b/test/Modules/Inputs/double-quotes/a.hmap.json new file mode 100644 index 000000000000..bdd383ce4150 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/a.hmap.json @@ -0,0 +1,6 @@ +{ + "mappings" : + { + "A.h" : "A/A.h" + } +} diff --git a/test/Modules/Inputs/double-quotes/flat-header-path/Z.h b/test/Modules/Inputs/double-quotes/flat-header-path/Z.h new file mode 100644 index 000000000000..db96b64962c1 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/flat-header-path/Z.h @@ -0,0 +1 @@ +#import "B.h" // Included from Z.h & A.h diff --git a/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap b/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap new file mode 100644 index 000000000000..34441b07018c --- /dev/null +++ b/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap @@ -0,0 +1,4 @@ +// double-quotes/flat-header-path/Z.modulemap +framework module Z { + header "Z.h" +} diff --git a/test/Modules/Inputs/double-quotes/x.hmap.json b/test/Modules/Inputs/double-quotes/x.hmap.json new file mode 100644 index 000000000000..2b6a05956469 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/x.hmap.json @@ -0,0 +1,7 @@ + +{ + "mappings" : + { + "X.h" : "X/X.h" + } +} diff --git a/test/Modules/Inputs/double-quotes/z.yaml b/test/Modules/Inputs/double-quotes/z.yaml new file mode 100644 index 000000000000..242f821346e6 --- /dev/null +++ b/test/Modules/Inputs/double-quotes/z.yaml @@ -0,0 +1,28 @@ +{ + 'version': 0, + 'case-sensitive': 'false', + 'roots': [ + { + 'type': 'directory', + 'name': "TEST_DIR/Z.framework/Headers", + 'contents': [ + { + 'type': 'file', + 'name': "Z.h", + 'external-contents': "TEST_DIR/flat-header-path/Z.h" + } + ] + }, + { + 'type': 'directory', + 'name': "TEST_DIR/Z.framework/Modules", + 'contents': [ + { + 'type': 'file', + 'name': "module.modulemap", + 'external-contents': "TEST_DIR/flat-header-path/Z.modulemap" + } + ] + } + ] +} diff --git a/test/Modules/double-quotes.m b/test/Modules/double-quotes.m new file mode 100644 index 000000000000..b0dbf662a180 --- /dev/null +++ b/test/Modules/double-quotes.m @@ -0,0 +1,39 @@ +// REQUIRES: shell + +// RUN: rm -rf %t +// RUN: mkdir %t + +// RUN: hmaptool write %S/Inputs/double-quotes/a.hmap.json %t/a.hmap +// RUN: hmaptool write %S/Inputs/double-quotes/x.hmap.json %t/x.hmap + +// RUN: sed -e "s:TEST_DIR:%S/Inputs/double-quotes:g" \ +// RUN: %S/Inputs/double-quotes/z.yaml > %t/z.yaml + +// The output with and without modules should be the same + +// RUN: %clang_cc1 \ +// RUN: -I %t/x.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \ +// RUN: -F%S/Inputs/double-quotes -I%S/Inputs/double-quotes \ +// RUN: -Wquoted-include-in-framework-header -fsyntax-only %s -verify + +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \ +// RUN: -I %t/x.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \ +// RUN: -F%S/Inputs/double-quotes -I%S/Inputs/double-quotes \ +// RUN: -Wquoted-include-in-framework-header -fsyntax-only %s \ +// RUN: 2>%t/stderr + +// The same warnings show up when modules is on but -verify doesn't get it +// because they only show up under the module A building context. +// RUN: FileCheck --input-file=%t/stderr %s +// CHECK: double-quoted include "A0.h" in framework header, expected angle-bracketed instead +// CHECK: double-quoted include "B.h" in framework header, expected angle-bracketed instead +// CHECK: double-quoted include "B.h" in framework header, expected angle-bracketed instead + +#import "A.h" +#import + +int bar() { return foo(); } + +// expected-warning@Inputs/double-quotes/A.framework/Headers/A.h:1{{double-quoted include "A0.h" in framework header, expected angle-bracketed instead}} +// expected-warning@Inputs/double-quotes/A.framework/Headers/A.h:2{{double-quoted include "B.h" in framework header, expected angle-bracketed instead}} +// expected-warning@Inputs/double-quotes/flat-header-path/Z.h:1{{double-quoted include "B.h" in framework header, expected angle-bracketed instead}} From 1cb0fd412f8bb6259cd621e3899f3617478653d7 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Wed, 20 Jun 2018 22:56:59 +0000 Subject: [PATCH 04/11] Use cast instead of dyn_cast_or_null. This addresses John's post-commit review feedback. https://reviews.llvm.org/rC335021#inline-2038 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335189 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDeclCXX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index f397949964b7..822d5ef254ac 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -7832,7 +7832,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, reinterpret_cast(FieldCollector->getCurFields()), FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList); - CheckCompletedCXXClass(dyn_cast_or_null(TagDecl)); + CheckCompletedCXXClass(cast(TagDecl)); } /// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared From 63711c3cd337a0d22617579a904af07481139611 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Wed, 20 Jun 2018 23:08:43 +0000 Subject: [PATCH 05/11] Fix hmaptool cmake file to work on Windows Unbreak a few windows buildbots: http://lab.llvm.org:8011/builders/clang-x64-ninja-win7/builds/11315 http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/10411/steps/test-check-all/logs/stdio git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335190 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/hmaptool/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/hmaptool/CMakeLists.txt b/utils/hmaptool/CMakeLists.txt index f5cc7d856a40..5573009d343a 100644 --- a/utils/hmaptool/CMakeLists.txt +++ b/utils/hmaptool/CMakeLists.txt @@ -1,14 +1,14 @@ set(CLANG_HMAPTOOL hmaptool) -add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL} +add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/${CLANG_HMAPTOOL} COMMAND ${CMAKE_COMMAND} -E make_directory - ${CMAKE_BINARY_DIR}/bin + ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL} - ${CMAKE_BINARY_DIR}/bin/ + ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL}) -list(APPEND Depends ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL}) +list(APPEND Depends ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/${CLANG_HMAPTOOL}) install(PROGRAMS ${CLANG_HMAPTOOL} DESTINATION bin) add_custom_target(hmaptool ALL DEPENDS ${Depends}) From fc8d6b0b1110ed2dfdf4c9196500306f84db6b3f Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 20 Jun 2018 23:36:55 +0000 Subject: [PATCH 06/11] When a dependent alignas is applied to a non-dependent typedef, prioritize the error for the bad subject over the error for the dependent / non-dependent mismatch. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335191 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDeclAttr.cpp | 23 +++++++++++----------- test/CXX/dcl.dcl/dcl.attr/dcl.align/p1.cpp | 6 ++++++ 2 files changed, 18 insertions(+), 11 deletions(-) create mode 100644 test/CXX/dcl.dcl/dcl.attr/dcl.align/p1.cpp diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 779192b8650b..614432b0e23b 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -3440,16 +3440,6 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &AL) { if (!AL.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E)) return; - if (E->isValueDependent()) { - if (const auto *TND = dyn_cast(D)) { - if (!TND->getUnderlyingType()->isDependentType()) { - S.Diag(AL.getLoc(), diag::err_alignment_dependent_typedef_name) - << E->getSourceRange(); - return; - } - } - } - S.AddAlignedAttr(AL.getRange(), D, E, AL.getAttributeSpellingListIndex(), AL.isPackExpansion()); } @@ -3496,7 +3486,18 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, } } - if (E->isTypeDependent() || E->isValueDependent()) { + if (E->isValueDependent()) { + // We can't support a dependent alignment on a non-dependent type, + // because we have no way to model that a type is "alignment-dependent" + // but not dependent in any other way. + if (const auto *TND = dyn_cast(D)) { + if (!TND->getUnderlyingType()->isDependentType()) { + Diag(AttrLoc, diag::err_alignment_dependent_typedef_name) + << E->getSourceRange(); + return; + } + } + // Save dependent expressions in the AST to be instantiated. AlignedAttr *AA = ::new (Context) AlignedAttr(TmpAttr); AA->setPackExpansion(IsPackExpansion); diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.align/p1.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p1.cpp new file mode 100644 index 000000000000..ec7b22f753f1 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.align/p1.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +typedef int A alignas(4); // expected-error {{'alignas' attribute only applies to variables, data members and tag types}} +template void f() { + typedef int B alignas(N); // expected-error {{'alignas' attribute only applies to variables, data members and tag types}} +} From 938c027c694efcb11be392ac8f9d0127a91cc1ef Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Thu, 21 Jun 2018 00:16:32 +0000 Subject: [PATCH 07/11] ASan docs: no_sanitize("address") works on globals. Summary: Mention that no_sanitize attribute can be used with globals. Reviewers: alekseyshl Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D48390 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335193 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/AddressSanitizer.rst | 14 +++++++++----- include/clang/Basic/AttrDocs.td | 21 +++++++++++---------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/docs/AddressSanitizer.rst b/docs/AddressSanitizer.rst index f58995576f91..20cf699ac0b9 100644 --- a/docs/AddressSanitizer.rst +++ b/docs/AddressSanitizer.rst @@ -197,13 +197,17 @@ this purpose. Disabling Instrumentation with ``__attribute__((no_sanitize("address")))`` -------------------------------------------------------------------------- -Some code should not be instrumented by AddressSanitizer. One may use the -function attribute ``__attribute__((no_sanitize("address")))`` (which has -deprecated synonyms `no_sanitize_address` and `no_address_safety_analysis`) to -disable instrumentation of a particular function. This attribute may not be -supported by other compilers, so we suggest to use it together with +Some code should not be instrumented by AddressSanitizer. One may use +the attribute ``__attribute__((no_sanitize("address")))`` (which has +deprecated synonyms `no_sanitize_address` and +`no_address_safety_analysis`) to disable instrumentation of a +particular function. This attribute may not be supported by other +compilers, so we suggest to use it together with ``__has_feature(address_sanitizer)``. +The same attribute used on a global variable prevents AddressSanitizer +from adding redzones around it and detecting out of bounds accesses. + Suppressing Errors in Recompiled Code (Blacklist) ------------------------------------------------- diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index 1cb510560d08..8210bf0a86a8 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -1804,13 +1804,14 @@ This attribute accepts a single parameter that must be one of the following: def NoSanitizeDocs : Documentation { let Category = DocCatFunction; let Content = [{ -Use the ``no_sanitize`` attribute on a function declaration to specify -that a particular instrumentation or set of instrumentations should not be -applied to that function. The attribute takes a list of string literals, -which have the same meaning as values accepted by the ``-fno-sanitize=`` -flag. For example, ``__attribute__((no_sanitize("address", "thread")))`` -specifies that AddressSanitizer and ThreadSanitizer should not be applied -to the function. +Use the ``no_sanitize`` attribute on a function or a global variable +declaration to specify that a particular instrumentation or set of +instrumentations should not be applied. The attribute takes a list of +string literals, which have the same meaning as values accepted by the +``-fno-sanitize=`` flag. For example, +``__attribute__((no_sanitize("address", "thread")))`` specifies that +AddressSanitizer and ThreadSanitizer should not be applied to the +function or variable. See :ref:`Controlling Code Generation ` for a full list of supported sanitizer flags. @@ -1825,9 +1826,9 @@ def NoSanitizeAddressDocs : Documentation { let Content = [{ .. _langext-address_sanitizer: -Use ``__attribute__((no_sanitize_address))`` on a function declaration to -specify that address safety instrumentation (e.g. AddressSanitizer) should -not be applied to that function. +Use ``__attribute__((no_sanitize_address))`` on a function or a global +variable declaration to specify that address safety instrumentation +(e.g. AddressSanitizer) should not be applied. }]; } From e642afa2d9a93ed56722d74ed06402995f8b5b18 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Thu, 21 Jun 2018 01:23:42 +0000 Subject: [PATCH 08/11] Revert "Fix hmaptool cmake file to work on Windows" This reverts commit 63711c3cd337a0d22617579a904af07481139611, due to breaking bots: http://lab.llvm.org:8011/builders/clang-x64-ninja-win7/builds/11315 http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/10411/steps/test-check-all/logs/stdio git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335194 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/hmaptool/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/hmaptool/CMakeLists.txt b/utils/hmaptool/CMakeLists.txt index 5573009d343a..f5cc7d856a40 100644 --- a/utils/hmaptool/CMakeLists.txt +++ b/utils/hmaptool/CMakeLists.txt @@ -1,14 +1,14 @@ set(CLANG_HMAPTOOL hmaptool) -add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/${CLANG_HMAPTOOL} +add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL} COMMAND ${CMAKE_COMMAND} -E make_directory - ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin + ${CMAKE_BINARY_DIR}/bin COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL} - ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/ + ${CMAKE_BINARY_DIR}/bin/ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL}) -list(APPEND Depends ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/${CLANG_HMAPTOOL}) +list(APPEND Depends ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL}) install(PROGRAMS ${CLANG_HMAPTOOL} DESTINATION bin) add_custom_target(hmaptool ALL DEPENDS ${Depends}) From 62edf8185082bbf882f74ee7aae04c91f93e92f8 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Thu, 21 Jun 2018 01:23:51 +0000 Subject: [PATCH 09/11] Revert "Warning for framework headers using double quote includes" This reverts commit 9b5ff2db7e31c4bb11a7d468260b068b41c7c285. Broke bots: http://lab.llvm.org:8011/builders/clang-x64-ninja-win7/builds/11315 http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/10411/steps/test-check-all/logs/stdio git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335195 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticGroups.td | 1 - include/clang/Basic/DiagnosticLexKinds.td | 5 -- lib/Lex/HeaderSearch.cpp | 65 +------------------ .../double-quotes/A.framework/Headers/A.h | 6 -- .../double-quotes/A.framework/Headers/A0.h | 1 - .../A.framework/Modules/module.modulemap | 5 -- test/Modules/Inputs/double-quotes/B.h | 1 - .../double-quotes/X.framework/Headers/X.h | 1 - .../X.framework/Modules/module.modulemap | 4 -- test/Modules/Inputs/double-quotes/a.hmap.json | 6 -- .../Inputs/double-quotes/flat-header-path/Z.h | 1 - .../flat-header-path/Z.modulemap | 4 -- test/Modules/Inputs/double-quotes/x.hmap.json | 7 -- test/Modules/Inputs/double-quotes/z.yaml | 28 -------- test/Modules/double-quotes.m | 39 ----------- 15 files changed, 1 insertion(+), 173 deletions(-) delete mode 100644 test/Modules/Inputs/double-quotes/A.framework/Headers/A.h delete mode 100644 test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h delete mode 100644 test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap delete mode 100644 test/Modules/Inputs/double-quotes/B.h delete mode 100644 test/Modules/Inputs/double-quotes/X.framework/Headers/X.h delete mode 100644 test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap delete mode 100644 test/Modules/Inputs/double-quotes/a.hmap.json delete mode 100644 test/Modules/Inputs/double-quotes/flat-header-path/Z.h delete mode 100644 test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap delete mode 100644 test/Modules/Inputs/double-quotes/x.hmap.json delete mode 100644 test/Modules/Inputs/double-quotes/z.yaml delete mode 100644 test/Modules/double-quotes.m diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 7cc9967738cf..643c178743ba 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -31,7 +31,6 @@ def AutoDisableVptrSanitizer : DiagGroup<"auto-disable-vptr-sanitizer">; def Availability : DiagGroup<"availability">; def Section : DiagGroup<"section">; def AutoImport : DiagGroup<"auto-import">; -def FrameworkHdrQuotedInclude : DiagGroup<"quoted-include-in-framework-header">; def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">; def CXXPre14CompatBinaryLiteral : DiagGroup<"c++98-c++11-compat-binary-literal">; def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index de6bffcdcaaa..9b7f7e677755 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -714,11 +714,6 @@ def warn_mmap_redundant_export_as : Warning< def err_mmap_submodule_export_as : Error< "only top-level modules can be re-exported as public">; -def warn_quoted_include_in_framework_header : Warning< - "double-quoted include \"%0\" in framework header, " - "expected angle-bracketed instead" - >, InGroup, DefaultIgnore; - def warn_auto_module_import : Warning< "treating #%select{include|import|include_next|__include_macros}0 as an " "import of module '%1'">, InGroup, DefaultIgnore; diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index 757cd097e4e5..1f2c339ea3c9 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -621,59 +621,6 @@ static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) { return CopyStr; } -static bool isFrameworkStylePath(StringRef Path, - SmallVectorImpl &FrameworkName) { - using namespace llvm::sys; - path::const_iterator I = path::begin(Path); - path::const_iterator E = path::end(Path); - - // Detect different types of framework style paths: - // - // ...Foo.framework/{Headers,PrivateHeaders} - // ...Foo.framework/Versions/{A,Current}/{Headers,PrivateHeaders} - // ...Foo.framework/Frameworks/Nested.framework/{Headers,PrivateHeaders} - // ... - // - // and some other variations among these lines. - int FoundComp = 0; - while (I != E) { - if (I->endswith(".framework")) { - FrameworkName.append(I->begin(), I->end()); - ++FoundComp; - } - if (*I == "Headers" || *I == "PrivateHeaders") - ++FoundComp; - ++I; - } - - return FoundComp >= 2; -} - -static void -diagnoseFrameworkInclude(DiagnosticsEngine &Diags, SourceLocation IncludeLoc, - StringRef Includer, StringRef IncludeFilename, - const FileEntry *IncludeFE, bool isAngled = false, - bool FoundByHeaderMap = false) { - SmallString<128> FromFramework, ToFramework; - if (!isFrameworkStylePath(Includer, FromFramework)) - return; - bool IsIncludeeInFramework = - isFrameworkStylePath(IncludeFE->getName(), ToFramework); - - if (!isAngled && !FoundByHeaderMap) { - SmallString<128> NewInclude("<"); - if (IsIncludeeInFramework) { - NewInclude += StringRef(ToFramework).drop_back(10); // drop .framework - NewInclude += "/"; - } - NewInclude += IncludeFilename; - NewInclude += ">"; - Diags.Report(IncludeLoc, diag::warn_quoted_include_in_framework_header) - << IncludeFilename - << FixItHint::CreateReplacement(IncludeLoc, NewInclude); - } -} - /// LookupFile - Given a "foo" or \ reference, look up the indicated file, /// return null on failure. isAngled indicates whether the file reference is /// for system \#include's or not (i.e. using <> instead of ""). Includers, if @@ -775,12 +722,8 @@ const FileEntry *HeaderSearch::LookupFile( RelativePath->clear(); RelativePath->append(Filename.begin(), Filename.end()); } - if (First) { - diagnoseFrameworkInclude(Diags, IncludeLoc, - IncluderAndDir.second->getName(), Filename, - FE); + if (First) return FE; - } // Otherwise, we found the path via MSVC header search rules. If // -Wmsvc-include is enabled, we have to keep searching to see if we @@ -891,12 +834,6 @@ const FileEntry *HeaderSearch::LookupFile( return MSFE; } - bool FoundByHeaderMap = !IsMapped ? false : *IsMapped; - if (!Includers.empty()) - diagnoseFrameworkInclude(Diags, IncludeLoc, - Includers.front().second->getName(), Filename, - FE, isAngled, FoundByHeaderMap); - // Remember this location for the next lookup we do. CacheLookup.HitIdx = i; return FE; diff --git a/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h b/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h deleted file mode 100644 index 17ceb83bb9ca..000000000000 --- a/test/Modules/Inputs/double-quotes/A.framework/Headers/A.h +++ /dev/null @@ -1,6 +0,0 @@ -#include "A0.h" -#include "B.h" - -#include "X.h" - -int foo(); diff --git a/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h b/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h deleted file mode 100644 index 79c6b8893ba4..000000000000 --- a/test/Modules/Inputs/double-quotes/A.framework/Headers/A0.h +++ /dev/null @@ -1 +0,0 @@ -// double-quotes/A.framework/Headers/A0.h diff --git a/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap b/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap deleted file mode 100644 index 09a887a8f489..000000000000 --- a/test/Modules/Inputs/double-quotes/A.framework/Modules/module.modulemap +++ /dev/null @@ -1,5 +0,0 @@ -// double-quotes/A.framework/Modules/module.modulemap -framework module A { - header "A.h" - header "A0.h" -} diff --git a/test/Modules/Inputs/double-quotes/B.h b/test/Modules/Inputs/double-quotes/B.h deleted file mode 100644 index 724faaef807d..000000000000 --- a/test/Modules/Inputs/double-quotes/B.h +++ /dev/null @@ -1 +0,0 @@ -// double-quotes/B.h diff --git a/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h b/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h deleted file mode 100644 index 0185751299c7..000000000000 --- a/test/Modules/Inputs/double-quotes/X.framework/Headers/X.h +++ /dev/null @@ -1 +0,0 @@ -// double-quotes/X.framework/Headers/X.h diff --git a/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap b/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap deleted file mode 100644 index 95524704c683..000000000000 --- a/test/Modules/Inputs/double-quotes/X.framework/Modules/module.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -// double-quotes/X.framework/Modules/module.modulemap -framework module X { - header "X.h" -} diff --git a/test/Modules/Inputs/double-quotes/a.hmap.json b/test/Modules/Inputs/double-quotes/a.hmap.json deleted file mode 100644 index bdd383ce4150..000000000000 --- a/test/Modules/Inputs/double-quotes/a.hmap.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "mappings" : - { - "A.h" : "A/A.h" - } -} diff --git a/test/Modules/Inputs/double-quotes/flat-header-path/Z.h b/test/Modules/Inputs/double-quotes/flat-header-path/Z.h deleted file mode 100644 index db96b64962c1..000000000000 --- a/test/Modules/Inputs/double-quotes/flat-header-path/Z.h +++ /dev/null @@ -1 +0,0 @@ -#import "B.h" // Included from Z.h & A.h diff --git a/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap b/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap deleted file mode 100644 index 34441b07018c..000000000000 --- a/test/Modules/Inputs/double-quotes/flat-header-path/Z.modulemap +++ /dev/null @@ -1,4 +0,0 @@ -// double-quotes/flat-header-path/Z.modulemap -framework module Z { - header "Z.h" -} diff --git a/test/Modules/Inputs/double-quotes/x.hmap.json b/test/Modules/Inputs/double-quotes/x.hmap.json deleted file mode 100644 index 2b6a05956469..000000000000 --- a/test/Modules/Inputs/double-quotes/x.hmap.json +++ /dev/null @@ -1,7 +0,0 @@ - -{ - "mappings" : - { - "X.h" : "X/X.h" - } -} diff --git a/test/Modules/Inputs/double-quotes/z.yaml b/test/Modules/Inputs/double-quotes/z.yaml deleted file mode 100644 index 242f821346e6..000000000000 --- a/test/Modules/Inputs/double-quotes/z.yaml +++ /dev/null @@ -1,28 +0,0 @@ -{ - 'version': 0, - 'case-sensitive': 'false', - 'roots': [ - { - 'type': 'directory', - 'name': "TEST_DIR/Z.framework/Headers", - 'contents': [ - { - 'type': 'file', - 'name': "Z.h", - 'external-contents': "TEST_DIR/flat-header-path/Z.h" - } - ] - }, - { - 'type': 'directory', - 'name': "TEST_DIR/Z.framework/Modules", - 'contents': [ - { - 'type': 'file', - 'name': "module.modulemap", - 'external-contents': "TEST_DIR/flat-header-path/Z.modulemap" - } - ] - } - ] -} diff --git a/test/Modules/double-quotes.m b/test/Modules/double-quotes.m deleted file mode 100644 index b0dbf662a180..000000000000 --- a/test/Modules/double-quotes.m +++ /dev/null @@ -1,39 +0,0 @@ -// REQUIRES: shell - -// RUN: rm -rf %t -// RUN: mkdir %t - -// RUN: hmaptool write %S/Inputs/double-quotes/a.hmap.json %t/a.hmap -// RUN: hmaptool write %S/Inputs/double-quotes/x.hmap.json %t/x.hmap - -// RUN: sed -e "s:TEST_DIR:%S/Inputs/double-quotes:g" \ -// RUN: %S/Inputs/double-quotes/z.yaml > %t/z.yaml - -// The output with and without modules should be the same - -// RUN: %clang_cc1 \ -// RUN: -I %t/x.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \ -// RUN: -F%S/Inputs/double-quotes -I%S/Inputs/double-quotes \ -// RUN: -Wquoted-include-in-framework-header -fsyntax-only %s -verify - -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache \ -// RUN: -I %t/x.hmap -iquote %t/a.hmap -ivfsoverlay %t/z.yaml \ -// RUN: -F%S/Inputs/double-quotes -I%S/Inputs/double-quotes \ -// RUN: -Wquoted-include-in-framework-header -fsyntax-only %s \ -// RUN: 2>%t/stderr - -// The same warnings show up when modules is on but -verify doesn't get it -// because they only show up under the module A building context. -// RUN: FileCheck --input-file=%t/stderr %s -// CHECK: double-quoted include "A0.h" in framework header, expected angle-bracketed instead -// CHECK: double-quoted include "B.h" in framework header, expected angle-bracketed instead -// CHECK: double-quoted include "B.h" in framework header, expected angle-bracketed instead - -#import "A.h" -#import - -int bar() { return foo(); } - -// expected-warning@Inputs/double-quotes/A.framework/Headers/A.h:1{{double-quoted include "A0.h" in framework header, expected angle-bracketed instead}} -// expected-warning@Inputs/double-quotes/A.framework/Headers/A.h:2{{double-quoted include "B.h" in framework header, expected angle-bracketed instead}} -// expected-warning@Inputs/double-quotes/flat-header-path/Z.h:1{{double-quoted include "B.h" in framework header, expected angle-bracketed instead}} From db9cf08b1f1519fc74c87b8fe3f13226e4cd80ac Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Thu, 21 Jun 2018 01:23:58 +0000 Subject: [PATCH 10/11] Revert "Add python tool to dump and construct header maps" This reverts commit fcfa2dd517ec1a6045a81e8247e346d630a22618. Broke bots: http://lab.llvm.org:8011/builders/clang-x64-ninja-win7/builds/11315 http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/10411/steps/test-check-all/logs/stdio git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335196 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 1 - test/CMakeLists.txt | 1 - test/Modules/crash-vfs-headermaps.m | 10 +- .../Inputs/headermap-rel/foo.hmap | Bin 0 -> 804 bytes .../Inputs/headermap-rel/foo.hmap.json | 6 - .../headermap-rel2/project-headers.hmap | Bin 0 -> 108 bytes .../headermap-rel2/project-headers.hmap.json | 6 - .../Inputs/nonportable-hmaps/foo.hmap | Bin 0 -> 102 bytes .../Inputs/nonportable-hmaps/foo.hmap.json | 6 - test/Preprocessor/headermap-rel.c | 8 +- test/Preprocessor/headermap-rel2.c | 9 +- .../nonportable-include-with-hmap.c | 4 +- utils/hmaptool/CMakeLists.txt | 16 - utils/hmaptool/hmaptool | 296 ------------------ 14 files changed, 19 insertions(+), 344 deletions(-) create mode 100644 test/Preprocessor/Inputs/headermap-rel/foo.hmap delete mode 100644 test/Preprocessor/Inputs/headermap-rel/foo.hmap.json create mode 100644 test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap delete mode 100644 test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap.json create mode 100644 test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap delete mode 100644 test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json delete mode 100644 utils/hmaptool/CMakeLists.txt delete mode 100755 utils/hmaptool/hmaptool diff --git a/CMakeLists.txt b/CMakeLists.txt index ae8835d751c0..ab81ec34b00d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -753,7 +753,6 @@ endif() if (LLVM_ADD_NATIVE_VISUALIZERS_TO_SOLUTION) add_subdirectory(utils/ClangVisualizers) endif() -add_subdirectory(utils/hmaptool) configure_file( ${CLANG_SOURCE_DIR}/include/clang/Config/config.h.cmake diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8d6db5348e08..8efe3600c540 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -54,7 +54,6 @@ list(APPEND CLANG_TEST_DEPS clang-rename clang-refactor clang-diff - hmaptool ) if(CLANG_ENABLE_STATIC_ANALYZER) diff --git a/test/Modules/crash-vfs-headermaps.m b/test/Modules/crash-vfs-headermaps.m index d33534602800..4f88f3ba1197 100644 --- a/test/Modules/crash-vfs-headermaps.m +++ b/test/Modules/crash-vfs-headermaps.m @@ -1,9 +1,15 @@ // REQUIRES: crash-recovery, shell, system-darwin +// This uses a headermap with this entry: +// Foo.h -> Foo/Foo.h + +// Copy out the headermap from test/Preprocessor/Inputs/headermap-rel and avoid +// adding another binary format to the repository. + // RUN: rm -rf %t -// RUN: mkdir -p %t/m %t/i/Foo.framework/Headers +// RUN: mkdir -p %t/m +// RUN: cp -a %S/../Preprocessor/Inputs/headermap-rel %t/i // RUN: echo '// Foo.h' > %t/i/Foo.framework/Headers/Foo.h -// RUN: hmaptool write %S/../Preprocessor/Inputs/headermap-rel/foo.hmap.json %t/i/foo.hmap // RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \ // RUN: %clang -fsyntax-only -fmodules -fmodules-cache-path=%t/m %s \ diff --git a/test/Preprocessor/Inputs/headermap-rel/foo.hmap b/test/Preprocessor/Inputs/headermap-rel/foo.hmap new file mode 100644 index 0000000000000000000000000000000000000000..783c64e67bb80a38f23845ed54fac43e2dc101a4 GIT binary patch literal 804 ycmXR&%*|kAU|^77W?%r(4nWKa#KRSU{KyW(AbJ#xh5*hGaLdov%U}SK`V0V(7zHB$ literal 0 HcmV?d00001 diff --git a/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json b/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json deleted file mode 100644 index ccfd911f0f7f..000000000000 --- a/test/Preprocessor/Inputs/headermap-rel/foo.hmap.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "mappings" : - { - "Foo.h" : "Foo/Foo.h" - } -} diff --git a/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap b/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap new file mode 100644 index 0000000000000000000000000000000000000000..a0770fb251242a3eec33dda98beab4f3d38adef8 GIT binary patch literal 108 zcmXR&%*|kAU|{e7Vi3&DdU3;?O;17dNI;^O?=)Qr@`l++@<42FQB{FKt<5`9!r E0L3N_r2qf` literal 0 HcmV?d00001 diff --git a/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap.json b/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap.json deleted file mode 100644 index e03703b1bb06..000000000000 --- a/test/Preprocessor/Inputs/headermap-rel2/project-headers.hmap.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "mappings" : - { - "someheader.h" : "Product/someheader.h" - } -} diff --git a/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap b/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap new file mode 100644 index 0000000000000000000000000000000000000000..9036f208711c4c0b8f0fc89c58648c63658b863f GIT binary patch literal 102 zcmXR&%*|kAU|{e7Vi3&&#DYMK3_#-CKrDeQh|YG)&({ZHy$pto)Wnq3qGJ6tpa=s* F2moPe3vU1b literal 0 HcmV?d00001 diff --git a/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json b/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json deleted file mode 100644 index c69f1df77253..000000000000 --- a/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "mappings" : - { - "Foo/Foo.h" : "headers/foo/Foo.h" - } -} diff --git a/test/Preprocessor/headermap-rel.c b/test/Preprocessor/headermap-rel.c index 91f0d957e5a6..38500a70f697 100644 --- a/test/Preprocessor/headermap-rel.c +++ b/test/Preprocessor/headermap-rel.c @@ -1,6 +1,8 @@ -// RUN: rm -f %t.hmap -// RUN: hmaptool write %S/Inputs/headermap-rel/foo.hmap.json %t.hmap -// RUN: %clang_cc1 -E %s -o %t.i -I %t.hmap -F %S/Inputs/headermap-rel + +// This uses a headermap with this entry: +// Foo.h -> Foo/Foo.h + +// RUN: %clang_cc1 -E %s -o %t.i -I %S/Inputs/headermap-rel/foo.hmap -F %S/Inputs/headermap-rel // RUN: FileCheck %s -input-file %t.i // CHECK: Foo.h is parsed diff --git a/test/Preprocessor/headermap-rel2.c b/test/Preprocessor/headermap-rel2.c index 172821efa425..d61f3385b22d 100644 --- a/test/Preprocessor/headermap-rel2.c +++ b/test/Preprocessor/headermap-rel2.c @@ -1,7 +1,8 @@ -// RUN: rm -f %t.hmap -// RUN: hmaptool write %S/Inputs/headermap-rel2/project-headers.hmap.json %t.hmap -// RUN: %clang_cc1 -v -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H -// RUN: %clang_cc1 -fsyntax-only %s -iquote %t.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out +// This uses a headermap with this entry: +// someheader.h -> Product/someheader.h + +// RUN: %clang_cc1 -v -fsyntax-only %s -iquote %S/Inputs/headermap-rel2/project-headers.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H +// RUN: %clang_cc1 -fsyntax-only %s -iquote %S/Inputs/headermap-rel2/project-headers.hmap -isystem %S/Inputs/headermap-rel2/system/usr/include -I %S/Inputs/headermap-rel2 -H 2> %t.out // RUN: FileCheck %s -input-file %t.out // CHECK: Product/someheader.h diff --git a/test/Preprocessor/nonportable-include-with-hmap.c b/test/Preprocessor/nonportable-include-with-hmap.c index 0190d13498a2..fc958e7e5e3f 100644 --- a/test/Preprocessor/nonportable-include-with-hmap.c +++ b/test/Preprocessor/nonportable-include-with-hmap.c @@ -1,7 +1,5 @@ -// RUN: rm -f %t.hmap -// RUN: hmaptool write %S/Inputs/nonportable-hmaps/foo.hmap.json %t.hmap // RUN: %clang_cc1 -Eonly \ -// RUN: -I%t.hmap \ +// RUN: -I%S/Inputs/nonportable-hmaps/foo.hmap \ // RUN: -I%S/Inputs/nonportable-hmaps \ // RUN: %s -verify // diff --git a/utils/hmaptool/CMakeLists.txt b/utils/hmaptool/CMakeLists.txt deleted file mode 100644 index f5cc7d856a40..000000000000 --- a/utils/hmaptool/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -set(CLANG_HMAPTOOL hmaptool) - -add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL} - COMMAND ${CMAKE_COMMAND} -E make_directory - ${CMAKE_BINARY_DIR}/bin - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL} - ${CMAKE_BINARY_DIR}/bin/ - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${CLANG_HMAPTOOL}) - -list(APPEND Depends ${CMAKE_BINARY_DIR}/bin/${CLANG_HMAPTOOL}) -install(PROGRAMS ${CLANG_HMAPTOOL} DESTINATION bin) - -add_custom_target(hmaptool ALL DEPENDS ${Depends}) -set_target_properties(hmaptool PROPERTIES FOLDER "Utils") - diff --git a/utils/hmaptool/hmaptool b/utils/hmaptool/hmaptool deleted file mode 100755 index 2b1ca7436c3f..000000000000 --- a/utils/hmaptool/hmaptool +++ /dev/null @@ -1,296 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function - -import json -import optparse -import os -import struct -import sys - -### - -k_header_magic_LE = 'pamh' -k_header_magic_BE = 'hmap' - -def hmap_hash(str): - """hash(str) -> int - - Apply the "well-known" headermap hash function. - """ - - return sum((ord(c.lower()) * 13 - for c in str), 0) - -class HeaderMap(object): - @staticmethod - def frompath(path): - with open(path, 'rb') as f: - magic = f.read(4) - if magic == k_header_magic_LE: - endian_code = '<' - elif magic == k_header_magic_BE: - endian_code = '>' - else: - raise SystemExit("error: %s: not a headermap" % ( - path,)) - - # Read the header information. - header_fmt = endian_code + 'HHIIII' - header_size = struct.calcsize(header_fmt) - data = f.read(header_size) - if len(data) != header_size: - raise SystemExit("error: %s: truncated headermap header" % ( - path,)) - - (version, reserved, strtable_offset, num_entries, - num_buckets, max_value_len) = struct.unpack(header_fmt, data) - - if version != 1: - raise SystemExit("error: %s: unknown headermap version: %r" % ( - path, version)) - if reserved != 0: - raise SystemExit("error: %s: invalid reserved value in header" % ( - path,)) - - # The number of buckets must be a power of two. - if num_buckets == 0 or (num_buckets & num_buckets - 1) != 0: - raise SystemExit("error: %s: invalid number of buckets" % ( - path,)) - - # Read all of the buckets. - bucket_fmt = endian_code + 'III' - bucket_size = struct.calcsize(bucket_fmt) - buckets_data = f.read(num_buckets * bucket_size) - if len(buckets_data) != num_buckets * bucket_size: - raise SystemExit("error: %s: truncated headermap buckets" % ( - path,)) - buckets = [struct.unpack(bucket_fmt, - buckets_data[i*bucket_size:(i+1)*bucket_size]) - for i in range(num_buckets)] - - # Read the string table; the format doesn't explicitly communicate the - # size of the string table (which is dumb), so assume it is the rest of - # the file. - f.seek(0, 2) - strtable_size = f.tell() - strtable_offset - f.seek(strtable_offset) - - if strtable_size == 0: - raise SystemExit("error: %s: unable to read zero-sized string table"%( - path,)) - strtable = f.read(strtable_size) - - if len(strtable) != strtable_size: - raise SystemExit("error: %s: unable to read complete string table"%( - path,)) - if strtable[-1] != '\0': - raise SystemExit("error: %s: invalid string table in headermap" % ( - path,)) - - return HeaderMap(num_entries, buckets, strtable) - - def __init__(self, num_entries, buckets, strtable): - self.num_entries = num_entries - self.buckets = buckets - self.strtable = strtable - - def get_string(self, idx): - if idx >= len(self.strtable): - raise SystemExit("error: %s: invalid string index" % ( - path,)) - end_idx = self.strtable.index('\0', idx) - return self.strtable[idx:end_idx] - - @property - def mappings(self): - for key_idx,prefix_idx,suffix_idx in self.buckets: - if key_idx == 0: - continue - yield (self.get_string(key_idx), - self.get_string(prefix_idx) + self.get_string(suffix_idx)) - -### - -def action_dump(name, args): - "dump a headermap file" - - parser = optparse.OptionParser("%%prog %s [options] " % ( - name,)) - parser.add_option("-v", "--verbose", dest="verbose", - help="show more verbose output [%default]", - action="store_true", default=False) - (opts, args) = parser.parse_args(args) - - if len(args) != 1: - parser.error("invalid number of arguments") - - path, = args - - hmap = HeaderMap.frompath(path) - - # Dump all of the buckets. - print ('Header Map: %s' % (path,)) - if opts.verbose: - print ('headermap: %r' % (path,)) - print (' num entries: %d' % (hmap.num_entries,)) - print (' num buckets: %d' % (len(hmap.buckets),)) - print (' string table size: %d' % (len(hmap.strtable),)) - for i,bucket in enumerate(hmap.buckets): - key_idx,prefix_idx,suffix_idx = bucket - - if key_idx == 0: - continue - - # Get the strings. - key = hmap.get_string(key_idx) - prefix = hmap.get_string(prefix_idx) - suffix = hmap.get_string(suffix_idx) - - print (" bucket[%d]: %r -> (%r, %r) -- %d" % ( - i, key, prefix, suffix, (hmap_hash(key) & (num_buckets - 1)))) - else: - mappings = sorted(hmap.mappings) - for key,value in mappings: - print ("%s -> %s" % (key, value)) - print () - -def next_power_of_two(value): - if value < 0: - raise ArgumentError - return 1 if value == 0 else 2**(value - 1).bit_length() - -def action_write(name, args): - "write a headermap file from a JSON definition" - - parser = optparse.OptionParser("%%prog %s [options] " % ( - name,)) - (opts, args) = parser.parse_args(args) - - if len(args) != 2: - parser.error("invalid number of arguments") - - input_path,output_path = args - - with open(input_path, "r") as f: - input_data = json.load(f) - - # Compute the headermap contents, we make a table that is 1/3 full. - mappings = input_data['mappings'] - num_buckets = next_power_of_two(len(mappings) * 3) - - table = [(0, 0, 0) - for i in range(num_buckets)] - max_value_len = 0 - strtable = "\0" - for key,value in mappings.items(): - if not isinstance(key, str): - key = key.decode('utf-8') - if not isinstance(value, str): - value = value.decode('utf-8') - max_value_len = max(max_value_len, len(value)) - - key_idx = len(strtable) - strtable += key + '\0' - prefix = os.path.dirname(value) + '/' - suffix = os.path.basename(value) - prefix_idx = len(strtable) - strtable += prefix + '\0' - suffix_idx = len(strtable) - strtable += suffix + '\0' - - hash = hmap_hash(key) - for i in range(num_buckets): - idx = (hash + i) % num_buckets - if table[idx][0] == 0: - table[idx] = (key_idx, prefix_idx, suffix_idx) - break - else: - raise RuntimeError - - endian_code = '<' - magic = k_header_magic_LE - magic_size = 4 - header_fmt = endian_code + 'HHIIII' - header_size = struct.calcsize(header_fmt) - bucket_fmt = endian_code + 'III' - bucket_size = struct.calcsize(bucket_fmt) - strtable_offset = magic_size + header_size + num_buckets * bucket_size - header = (1, 0, strtable_offset, len(mappings), - num_buckets, max_value_len) - - # Write out the headermap. - with open(output_path, 'wb') as f: - f.write(magic.encode()) - f.write(struct.pack(header_fmt, *header)) - for bucket in table: - f.write(struct.pack(bucket_fmt, *bucket)) - f.write(strtable.encode()) - -def action_tovfs(name, args): - "convert a headermap to a VFS layout" - - parser = optparse.OptionParser("%%prog %s [options] " % ( - name,)) - parser.add_option("", "--build-path", dest="build_path", - help="build path prefix", - action="store", type=str) - (opts, args) = parser.parse_args(args) - - if len(args) != 2: - parser.error("invalid number of arguments") - if opts.build_path is None: - parser.error("--build-path is required") - - input_path,output_path = args - - hmap = HeaderMap.frompath(input_path) - - # Create the table for all the objects. - vfs = {} - vfs['version'] = 0 - build_dir_contents = [] - vfs['roots'] = [{ - 'name' : opts.build_path, - 'type' : 'directory', - 'contents' : build_dir_contents }] - - # We assume we are mapping framework paths, so a key of "Foo/Bar.h" maps to - # "/Foo.framework/Headers/Bar.h". - for key,value in hmap.mappings: - # If this isn't a framework style mapping, ignore it. - components = key.split('/') - if len(components) != 2: - continue - framework_name,header_name = components - build_dir_contents.append({ - 'name' : '%s.framework/Headers/%s' % (framework_name, - header_name), - 'type' : 'file', - 'external-contents' : value }) - - with open(output_path, 'w') as f: - json.dump(vfs, f, indent=2) - -commands = dict((name[7:].replace("_","-"), f) - for name,f in locals().items() - if name.startswith('action_')) - -def usage(): - print ("Usage: %s command [options]" % ( - os.path.basename(sys.argv[0])), file=sys.stderr) - print (file=sys.stderr) - print ("Available commands:", file=sys.stderr) - cmds_width = max(map(len, commands)) - for name,func in sorted(commands.items()): - print (" %-*s - %s" % (cmds_width, name, func.__doc__), file=sys.stderr) - sys.exit(1) - -def main(): - if len(sys.argv) < 2 or sys.argv[1] not in commands: - usage() - - cmd = sys.argv[1] - commands[cmd](cmd, sys.argv[2:]) - -if __name__ == '__main__': - main() From 3cf091f2774c4050a4f6b8fccc5bbb1c856aff50 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 21 Jun 2018 05:01:01 +0000 Subject: [PATCH 11/11] [X86] Remove masking from the 512-bit floating point max/min builtins. Use select in IR instead. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@335200 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/BuiltinsX86.def | 8 +- lib/Headers/avx512fintrin.h | 204 +++++++++++----------------- lib/Sema/SemaChecking.cpp | 10 +- test/CodeGen/avx512f-builtins.c | 55 +++++--- 4 files changed, 121 insertions(+), 156 deletions(-) diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index c044a7875720..2128c371396e 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -908,10 +908,10 @@ TARGET_BUILTIN(__builtin_ia32_cvtps2dq512_mask, "V16iV16fV16iUsIi", "nc", "avx51 TARGET_BUILTIN(__builtin_ia32_cvtpd2dq512_mask, "V8iV8dV8iUcIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_cvtps2udq512_mask, "V16iV16fV16iUsIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_cvtpd2udq512_mask, "V8iV8dV8iUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_minps512_mask, "V16fV16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_minpd512_mask, "V8dV8dV8dV8dUcIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_maxps512_mask, "V16fV16fV16fV16fUsIi", "nc", "avx512f") -TARGET_BUILTIN(__builtin_ia32_maxpd512_mask, "V8dV8dV8dV8dUcIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_minps512, "V16fV16fV16fIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_minpd512, "V8dV8dV8dIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_maxps512, "V16fV16fV16fIi", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_maxpd512, "V8dV8dV8dIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_cvtdq2ps512_mask, "V16fV16iV16fUsIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_cvtudq2ps512_mask, "V16fV16iV16fUsIi", "nc", "avx512f") TARGET_BUILTIN(__builtin_ia32_cvtpd2ps512_mask, "V8fV8dV8fUcIi", "nc", "avx512f") diff --git a/lib/Headers/avx512fintrin.h b/lib/Headers/avx512fintrin.h index 12b5f6040580..b2f6e280312f 100644 --- a/lib/Headers/avx512fintrin.h +++ b/lib/Headers/avx512fintrin.h @@ -944,104 +944,78 @@ _mm512_maskz_sub_epi32(__mmask16 __U, __m512i __A, __m512i __B) (__v16si)_mm512_setzero_si512()); } +#define _mm512_max_round_pd(A, B, R) \ + (__m512d)__builtin_ia32_maxpd512((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(R)) + #define _mm512_mask_max_round_pd(W, U, A, B, R) \ - (__m512d)__builtin_ia32_maxpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(W), (__mmask8)(U), \ - (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_max_round_pd((A), (B), (R)), \ + (__v8df)(W)) #define _mm512_maskz_max_round_pd(U, A, B, R) \ - (__m512d)__builtin_ia32_maxpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_setzero_pd(), \ - (__mmask8)(U), (int)(R)) - -#define _mm512_max_round_pd(A, B, R) \ - (__m512d)__builtin_ia32_maxpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_undefined_pd(), \ - (__mmask8)-1, (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_max_round_pd((A), (B), (R)), \ + (__v8df)_mm512_setzero_pd()) static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_max_pd(__m512d __A, __m512d __B) { - return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A, - (__v8df) __B, - (__v8df) - _mm512_setzero_pd (), - (__mmask8) -1, - _MM_FROUND_CUR_DIRECTION); + return (__m512d) __builtin_ia32_maxpd512((__v8df) __A, (__v8df) __B, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask_max_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { - return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A, - (__v8df) __B, - (__v8df) __W, - (__mmask8) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512d)__builtin_ia32_selectpd_512(__U, + (__v8df)_mm512_max_pd(__A, __B), + (__v8df)__W); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_maskz_max_pd (__mmask8 __U, __m512d __A, __m512d __B) { - return (__m512d) __builtin_ia32_maxpd512_mask ((__v8df) __A, - (__v8df) __B, - (__v8df) - _mm512_setzero_pd (), - (__mmask8) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512d)__builtin_ia32_selectpd_512(__U, + (__v8df)_mm512_max_pd(__A, __B), + (__v8df)_mm512_setzero_pd()); } +#define _mm512_max_round_ps(A, B, R) \ + (__m512)__builtin_ia32_maxps512((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(R)) + #define _mm512_mask_max_round_ps(W, U, A, B, R) \ - (__m512)__builtin_ia32_maxps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(W), (__mmask16)(U), \ - (int)(R)) + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_max_round_ps((A), (B), (R)), \ + (__v16sf)(W)) #define _mm512_maskz_max_round_ps(U, A, B, R) \ - (__m512)__builtin_ia32_maxps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_setzero_ps(), \ - (__mmask16)(U), (int)(R)) - -#define _mm512_max_round_ps(A, B, R) \ - (__m512)__builtin_ia32_maxps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_undefined_ps(), \ - (__mmask16)-1, (int)(R)) + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_max_round_ps((A), (B), (R)), \ + (__v16sf)_mm512_setzero_ps()) static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_max_ps(__m512 __A, __m512 __B) { - return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) - _mm512_setzero_ps (), - (__mmask16) -1, - _MM_FROUND_CUR_DIRECTION); + return (__m512) __builtin_ia32_maxps512((__v16sf) __A, (__v16sf) __B, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask_max_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { - return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) __W, - (__mmask16) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512)__builtin_ia32_selectps_512(__U, + (__v16sf)_mm512_max_ps(__A, __B), + (__v16sf)__W); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_maskz_max_ps (__mmask16 __U, __m512 __A, __m512 __B) { - return (__m512) __builtin_ia32_maxps512_mask ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) - _mm512_setzero_ps (), - (__mmask16) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512)__builtin_ia32_selectps_512(__U, + (__v16sf)_mm512_max_ps(__A, __B), + (__v16sf)_mm512_setzero_ps()); } static __inline__ __m128 __DEFAULT_FN_ATTRS @@ -1205,104 +1179,78 @@ _mm512_maskz_max_epu64 (__mmask8 __M, __m512i __A, __m512i __B) (__v8di)_mm512_setzero_si512()); } +#define _mm512_min_round_pd(A, B, R) \ + (__m512d)__builtin_ia32_minpd512((__v8df)(__m512d)(A), \ + (__v8df)(__m512d)(B), (int)(R)) + #define _mm512_mask_min_round_pd(W, U, A, B, R) \ - (__m512d)__builtin_ia32_minpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)(__m512d)(W), (__mmask8)(U), \ - (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_min_round_pd((A), (B), (R)), \ + (__v8df)(W)) #define _mm512_maskz_min_round_pd(U, A, B, R) \ - (__m512d)__builtin_ia32_minpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_setzero_pd(), \ - (__mmask8)(U), (int)(R)) - -#define _mm512_min_round_pd(A, B, R) \ - (__m512d)__builtin_ia32_minpd512_mask((__v8df)(__m512d)(A), \ - (__v8df)(__m512d)(B), \ - (__v8df)_mm512_undefined_pd(), \ - (__mmask8)-1, (int)(R)) + (__m512d)__builtin_ia32_selectpd_512((__mmask8)(U), \ + (__v8df)_mm512_min_round_pd((A), (B), (R)), \ + (__v8df)_mm512_setzero_pd()) static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_min_pd(__m512d __A, __m512d __B) { - return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A, - (__v8df) __B, - (__v8df) - _mm512_setzero_pd (), - (__mmask8) -1, - _MM_FROUND_CUR_DIRECTION); + return (__m512d) __builtin_ia32_minpd512((__v8df) __A, (__v8df) __B, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_mask_min_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { - return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A, - (__v8df) __B, - (__v8df) __W, - (__mmask8) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512d)__builtin_ia32_selectpd_512(__U, + (__v8df)_mm512_min_pd(__A, __B), + (__v8df)__W); } -#define _mm512_mask_min_round_ps(W, U, A, B, R) \ - (__m512)__builtin_ia32_minps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)(__m512)(W), (__mmask16)(U), \ - (int)(R)) - -#define _mm512_maskz_min_round_ps(U, A, B, R) \ - (__m512)__builtin_ia32_minps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_setzero_ps(), \ - (__mmask16)(U), (int)(R)) - -#define _mm512_min_round_ps(A, B, R) \ - (__m512)__builtin_ia32_minps512_mask((__v16sf)(__m512)(A), \ - (__v16sf)(__m512)(B), \ - (__v16sf)_mm512_undefined_ps(), \ - (__mmask16)-1, (int)(R)) - static __inline__ __m512d __DEFAULT_FN_ATTRS _mm512_maskz_min_pd (__mmask8 __U, __m512d __A, __m512d __B) { - return (__m512d) __builtin_ia32_minpd512_mask ((__v8df) __A, - (__v8df) __B, - (__v8df) - _mm512_setzero_pd (), - (__mmask8) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512d)__builtin_ia32_selectpd_512(__U, + (__v8df)_mm512_min_pd(__A, __B), + (__v8df)_mm512_setzero_pd()); } +#define _mm512_min_round_ps(A, B, R) \ + (__m512)__builtin_ia32_minps512((__v16sf)(__m512)(A), \ + (__v16sf)(__m512)(B), (int)(R)) + +#define _mm512_mask_min_round_ps(W, U, A, B, R) \ + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_min_round_ps((A), (B), (R)), \ + (__v16sf)(W)) + +#define _mm512_maskz_min_round_ps(U, A, B, R) \ + (__m512)__builtin_ia32_selectps_512((__mmask16)(U), \ + (__v16sf)_mm512_min_round_ps((A), (B), (R)), \ + (__v16sf)_mm512_setzero_ps()) + static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_min_ps(__m512 __A, __m512 __B) { - return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) - _mm512_setzero_ps (), - (__mmask16) -1, - _MM_FROUND_CUR_DIRECTION); + return (__m512) __builtin_ia32_minps512((__v16sf) __A, (__v16sf) __B, + _MM_FROUND_CUR_DIRECTION); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_mask_min_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { - return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) __W, - (__mmask16) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512)__builtin_ia32_selectps_512(__U, + (__v16sf)_mm512_min_ps(__A, __B), + (__v16sf)__W); } static __inline__ __m512 __DEFAULT_FN_ATTRS _mm512_maskz_min_ps (__mmask16 __U, __m512 __A, __m512 __B) { - return (__m512) __builtin_ia32_minps512_mask ((__v16sf) __A, - (__v16sf) __B, - (__v16sf) - _mm512_setzero_ps (), - (__mmask16) __U, - _MM_FROUND_CUR_DIRECTION); + return (__m512)__builtin_ia32_selectps_512(__U, + (__v16sf)_mm512_min_ps(__A, __B), + (__v16sf)_mm512_setzero_ps()); } static __inline__ __m128 __DEFAULT_FN_ATTRS diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 237484a4caab..9a05d9f00e55 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2298,6 +2298,12 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_vcvttss2usi64: ArgNum = 1; break; + case X86::BI__builtin_ia32_maxpd512: + case X86::BI__builtin_ia32_maxps512: + case X86::BI__builtin_ia32_minpd512: + case X86::BI__builtin_ia32_minps512: + ArgNum = 2; + break; case X86::BI__builtin_ia32_cvtps2pd512_mask: case X86::BI__builtin_ia32_cvttpd2dq512_mask: case X86::BI__builtin_ia32_cvttpd2qq512_mask: @@ -2327,12 +2333,8 @@ bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) { case X86::BI__builtin_ia32_cvtss2sd_round_mask: case X86::BI__builtin_ia32_getexpsd128_round_mask: case X86::BI__builtin_ia32_getexpss128_round_mask: - case X86::BI__builtin_ia32_maxpd512_mask: - case X86::BI__builtin_ia32_maxps512_mask: case X86::BI__builtin_ia32_maxsd_round_mask: case X86::BI__builtin_ia32_maxss_round_mask: - case X86::BI__builtin_ia32_minpd512_mask: - case X86::BI__builtin_ia32_minps512_mask: case X86::BI__builtin_ia32_minsd_round_mask: case X86::BI__builtin_ia32_minss_round_mask: case X86::BI__builtin_ia32_rcp28sd_round_mask: diff --git a/test/CodeGen/avx512f-builtins.c b/test/CodeGen/avx512f-builtins.c index 3942daa5c536..16ad42525546 100644 --- a/test/CodeGen/avx512f-builtins.c +++ b/test/CodeGen/avx512f-builtins.c @@ -8354,140 +8354,155 @@ float test_mm512_cvtss_f32(__m512 A) { __m512d test_mm512_mask_max_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_mask_max_pd - // CHECK: @llvm.x86.avx512.mask.max.pd.512 + // CHECK: @llvm.x86.avx512.max.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_max_pd (__W,__U,__A,__B); } __m512d test_mm512_maskz_max_pd (__mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_maskz_max_pd - // CHECK: @llvm.x86.avx512.mask.max.pd.512 + // CHECK: @llvm.x86.avx512.max.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_maskz_max_pd (__U,__A,__B); } __m512 test_mm512_mask_max_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_mask_max_ps - // CHECK: @llvm.x86.avx512.mask.max.ps.512 + // CHECK: @llvm.x86.avx512.max.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_max_ps (__W,__U,__A,__B); } __m512d test_mm512_mask_max_round_pd(__m512d __W,__mmask8 __U,__m512d __A,__m512d __B) { // CHECK-LABEL: @test_mm512_mask_max_round_pd - // CHECK: @llvm.x86.avx512.mask.max.pd.512 + // CHECK: @llvm.x86.avx512.max.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_max_round_pd(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512d test_mm512_maskz_max_round_pd(__mmask8 __U,__m512d __A,__m512d __B) { // CHECK-LABEL: @test_mm512_maskz_max_round_pd - // CHECK: @llvm.x86.avx512.mask.max.pd.512 + // CHECK: @llvm.x86.avx512.max.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_maskz_max_round_pd(__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512d test_mm512_max_round_pd(__m512d __A,__m512d __B) { // CHECK-LABEL: @test_mm512_max_round_pd - // CHECK: @llvm.x86.avx512.mask.max.pd.512 + // CHECK: @llvm.x86.avx512.max.pd.512 return _mm512_max_round_pd(__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512 test_mm512_maskz_max_ps (__mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_maskz_max_ps - // CHECK: @llvm.x86.avx512.mask.max.ps.512 + // CHECK: @llvm.x86.avx512.max.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_maskz_max_ps (__U,__A,__B); } __m512 test_mm512_mask_max_round_ps(__m512 __W,__mmask16 __U,__m512 __A,__m512 __B) { // CHECK-LABEL: @test_mm512_mask_max_round_ps - // CHECK: @llvm.x86.avx512.mask.max.ps.512 + // CHECK: @llvm.x86.avx512.max.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_max_round_ps(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512 test_mm512_maskz_max_round_ps(__mmask16 __U,__m512 __A,__m512 __B) { // CHECK-LABEL: @test_mm512_maskz_max_round_ps - // CHECK: @llvm.x86.avx512.mask.max.ps.512 + // CHECK: @llvm.x86.avx512.max.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_maskz_max_round_ps(__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512 test_mm512_max_round_ps(__m512 __A,__m512 __B) { // CHECK-LABEL: @test_mm512_max_round_ps - // CHECK: @llvm.x86.avx512.mask.max.ps.512 + // CHECK: @llvm.x86.avx512.max.ps.512 return _mm512_max_round_ps(__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512d test_mm512_mask_min_pd (__m512d __W, __mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_mask_min_pd - // CHECK: @llvm.x86.avx512.mask.min.pd.512 + // CHECK: @llvm.x86.avx512.min.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_min_pd (__W,__U,__A,__B); } __m512d test_mm512_maskz_min_pd (__mmask8 __U, __m512d __A, __m512d __B) { // CHECK-LABEL: @test_mm512_maskz_min_pd - // CHECK: @llvm.x86.avx512.mask.min.pd.512 + // CHECK: @llvm.x86.avx512.min.pd.512 return _mm512_maskz_min_pd (__U,__A,__B); } __m512d test_mm512_mask_min_round_pd(__m512d __W,__mmask8 __U,__m512d __A,__m512d __B) { // CHECK-LABEL: @test_mm512_mask_min_round_pd - // CHECK: @llvm.x86.avx512.mask.min.pd.512 + // CHECK: @llvm.x86.avx512.min.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_mask_min_round_pd(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512d test_mm512_maskz_min_round_pd(__mmask8 __U,__m512d __A,__m512d __B) { // CHECK-LABEL: @test_mm512_maskz_min_round_pd - // CHECK: @llvm.x86.avx512.mask.min.pd.512 + // CHECK: @llvm.x86.avx512.min.pd.512 + // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} return _mm512_maskz_min_round_pd(__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512d test_mm512_min_round_pd( __m512d __A,__m512d __B) { // CHECK-LABEL: @test_mm512_min_round_pd - // CHECK: @llvm.x86.avx512.mask.min.pd.512 + // CHECK: @llvm.x86.avx512.min.pd.512 return _mm512_min_round_pd(__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512 test_mm512_mask_min_ps (__m512 __W, __mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_mask_min_ps - // CHECK: @llvm.x86.avx512.mask.min.ps.512 + // CHECK: @llvm.x86.avx512.min.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_min_ps (__W,__U,__A,__B); } __m512 test_mm512_maskz_min_ps (__mmask16 __U, __m512 __A, __m512 __B) { // CHECK-LABEL: @test_mm512_maskz_min_ps - // CHECK: @llvm.x86.avx512.mask.min.ps.512 + // CHECK: @llvm.x86.avx512.min.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_maskz_min_ps (__U,__A,__B); } __m512 test_mm512_mask_min_round_ps(__m512 __W,__mmask16 __U,__m512 __A,__m512 __B) { // CHECK-LABEL: @test_mm512_mask_min_round_ps - // CHECK: @llvm.x86.avx512.mask.min.ps.512 + // CHECK: @llvm.x86.avx512.min.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_mask_min_round_ps(__W,__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512 test_mm512_maskz_min_round_ps(__mmask16 __U,__m512 __A,__m512 __B) { // CHECK-LABEL: @test_mm512_maskz_min_round_ps - // CHECK: @llvm.x86.avx512.mask.min.ps.512 + // CHECK: @llvm.x86.avx512.min.ps.512 + // CHECK: select <16 x i1> %{{.*}}, <16 x float> %{{.*}}, <16 x float> %{{.*}} return _mm512_maskz_min_round_ps(__U,__A,__B,_MM_FROUND_CUR_DIRECTION); } __m512 test_mm512_min_round_ps(__m512 __A,__m512 __B) { // CHECK-LABEL: @test_mm512_min_round_ps - // CHECK: @llvm.x86.avx512.mask.min.ps.512 + // CHECK: @llvm.x86.avx512.min.ps.512 return _mm512_min_round_ps(__A,__B,_MM_FROUND_CUR_DIRECTION); }