Skip to content

Commit

Permalink
Merged master:169c83208f3 into amd-gfx:b84e3982f0d
Browse files Browse the repository at this point in the history
Local branch amd-gfx b84e398 Merged master:1cf6f210a2e into amd-gfx:042be23e3d9
Remote branch master 169c832 [ldb/Reproducers] Add YamlRecorder and MultiProvider
  • Loading branch information
Sw authored and Sw committed Jul 10, 2020
2 parents b84e398 + 169c832 commit 68adaf5
Show file tree
Hide file tree
Showing 87 changed files with 1,585 additions and 533 deletions.
4 changes: 2 additions & 2 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3132,7 +3132,7 @@ Global objects must be constructed before the first kernel using the global obje
is executed and destroyed just after the last kernel using the program objects is
executed. In OpenCL v2.0 drivers there is no specific API for invoking global
constructors. However, an easy workaround would be to enqueue a constructor
initialization kernel that has a name ``@_GLOBAL__sub_I_<compiled file name>``.
initialization kernel that has a name ``_GLOBAL__sub_I_<compiled file name>``.
This kernel is only present if there are any global objects to be initialized in
the compiled binary. One way to check this is by passing ``CL_PROGRAM_KERNEL_NAMES``
to ``clGetProgramInfo`` (OpenCL v2.0 s5.8.7).
Expand All @@ -3148,7 +3148,7 @@ before running any kernels in which the objects are used.
clang -cl-std=clc++ test.cl
If there are any global objects to be initialized, the final binary will contain
the ``@_GLOBAL__sub_I_test.cl`` kernel to be enqueued.
the ``_GLOBAL__sub_I_test.cl`` kernel to be enqueued.

Global destructors can not be invoked in OpenCL v2.0 drivers. However, all memory used
for program scope objects is released on ``clReleaseProgram``.
Expand Down
13 changes: 11 additions & 2 deletions clang/lib/AST/DeclPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1374,15 +1374,24 @@ void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
}

void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
Out << "@implementation " << *PID->getClassInterface() << '(' << *PID <<")\n";
Out << "@implementation ";
if (const auto *CID = PID->getClassInterface())
Out << *CID;
else
Out << "<<error-type>>";
Out << '(' << *PID << ")\n";

VisitDeclContext(PID, false);
Out << "@end";
// FIXME: implement the rest...
}

void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) {
Out << "@interface " << *PID->getClassInterface();
Out << "@interface ";
if (const auto *CID = PID->getClassInterface())
Out << *CID;
else
Out << "<<error-type>>";
if (auto TypeParams = PID->getTypeParamList()) {
PrintObjCTypeParams(TypeParams);
}
Expand Down
1 change: 0 additions & 1 deletion clang/lib/AST/FormatString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,6 @@ ArgType::matchesType(ASTContext &C, QualType argTy) const {
QualType pointeeTy = PT->getPointeeType();
if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
switch (BT->getKind()) {
case BuiltinType::Void:
case BuiltinType::Char_U:
case BuiltinType::UChar:
case BuiltinType::Char_S:
Expand Down
26 changes: 26 additions & 0 deletions clang/test/CodeGen/debug-info-codeview-buildinfo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// UNSUPPORTED: s390x
// RUN: %clang_cl /c /Z7 /Fo%t.obj -- %s
// RUN: llvm-pdbutil dump --types %t.obj | FileCheck %s
// RUN: %clang_cl /c /Z7 /Fo%t.obj -fdebug-compilation-dir . -- %s
// RUN: llvm-pdbutil dump --types %t.obj | FileCheck %s --check-prefix RELATIVE

int main() { return 42; }

// CHECK: Types (.debug$T)
// CHECK: ============================================================
// CHECK: 0x[[PWD:.+]] | LF_STRING_ID [size = {{.+}}] ID: <no type>, String: [[PWDVAL:.+]]
// CHECK: 0x[[FILEPATH:.+]] | LF_STRING_ID [size = {{.+}}] ID: <no type>, String: [[FILEPATHVAL:.+[\\/]debug-info-codeview-buildinfo.c]]
// CHECK: 0x[[ZIPDB:.+]] | LF_STRING_ID [size = {{.+}}] ID: <no type>, String:
// CHECK: 0x[[TOOL:.+]] | LF_STRING_ID [size = {{.+}}] ID: <no type>, String: [[TOOLVAL:.+[\\/]clang.*]]
// CHECK: 0x[[CMDLINE:.+]] | LF_STRING_ID [size = {{.+}}] ID: <no type>, String: "-cc1
// CHECK: 0x{{.+}} | LF_BUILDINFO [size = {{.+}}]
// CHECK: 0x[[PWD]]: `[[PWDVAL]]`
// CHECK: 0x[[TOOL]]: `[[TOOLVAL]]`
// CHECK: 0x[[FILEPATH]]: `[[FILEPATHVAL]]`
// CHECK: 0x[[ZIPDB]]: ``
// CHECK: 0x[[CMDLINE]]: `"-cc1

// RELATIVE: Types (.debug$T)
// RELATIVE: ============================================================
// RELATIVE: 0x{{.+}} | LF_BUILDINFO [size = {{.+}}]
// RELATIVE: 0x{{.+}}: `.`
7 changes: 7 additions & 0 deletions clang/test/Sema/format-strings.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,8 +290,11 @@ void test11(void *p, char *s) {
printf("%0p", p); // expected-warning{{flag '0' results in undefined behavior with 'p' conversion specifier}}
printf("%s", s); // no-warning
printf("%+s", p); // expected-warning{{flag '+' results in undefined behavior with 's' conversion specifier}}
// expected-warning@-1 {{format specifies type 'char *' but the argument has type 'void *'}}
printf("% s", p); // expected-warning{{flag ' ' results in undefined behavior with 's' conversion specifier}}
// expected-warning@-1 {{format specifies type 'char *' but the argument has type 'void *'}}
printf("%0s", p); // expected-warning{{flag '0' results in undefined behavior with 's' conversion specifier}}
// expected-warning@-1 {{format specifies type 'char *' but the argument has type 'void *'}}
}

void test12(char *b) {
Expand Down Expand Up @@ -707,3 +710,7 @@ void PR30481() {
// This caused crashes due to invalid casts.
printf(1 > 0); // expected-warning{{format string is not a string literal}} expected-warning{{incompatible integer to pointer conversion}} expected-note@format-strings.c:*{{passing argument to parameter here}} expected-note{{to avoid this}}
}

void test_printf_opaque_ptr(void *op) {
printf("%s", op); // expected-warning{{format specifies type 'char *' but the argument has type 'void *'}}
}
34 changes: 23 additions & 11 deletions clang/unittests/AST/DeclPrinterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,16 @@ ::testing::AssertionResult
PrintedDeclMatches(StringRef Code, const std::vector<std::string> &Args,
const DeclarationMatcher &NodeMatch,
StringRef ExpectedPrinted, StringRef FileName,
PrintingPolicyModifier PolicyModifier = nullptr) {
PrintingPolicyModifier PolicyModifier = nullptr,
bool AllowError = false) {
PrintMatch Printer(PolicyModifier);
MatchFinder Finder;
Finder.addMatcher(NodeMatch, &Printer);
std::unique_ptr<FrontendActionFactory> Factory(
newFrontendActionFactory(&Finder));

if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName))
if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName) &&
!AllowError)
return testing::AssertionFailure()
<< "Parsing error in \"" << Code.str() << "\"";

Expand Down Expand Up @@ -170,16 +172,12 @@ PrintedDeclCXX1ZMatches(StringRef Code, const DeclarationMatcher &NodeMatch,
"input.cc");
}

::testing::AssertionResult PrintedDeclObjCMatches(
StringRef Code,
const DeclarationMatcher &NodeMatch,
StringRef ExpectedPrinted) {
::testing::AssertionResult
PrintedDeclObjCMatches(StringRef Code, const DeclarationMatcher &NodeMatch,
StringRef ExpectedPrinted, bool AllowError = false) {
std::vector<std::string> Args(1, "");
return PrintedDeclMatches(Code,
Args,
NodeMatch,
ExpectedPrinted,
"input.m");
return PrintedDeclMatches(Code, Args, NodeMatch, ExpectedPrinted, "input.m",
/*PolicyModifier=*/nullptr, AllowError);
}

} // unnamed namespace
Expand Down Expand Up @@ -1321,3 +1319,17 @@ TEST(DeclPrinter, TestObjCProtocol2) {
namedDecl(hasName("P1")).bind("id"),
"@protocol P1<P2>\n@end"));
}

TEST(DeclPrinter, TestObjCCategoryInvalidInterface) {
ASSERT_TRUE(PrintedDeclObjCMatches(
"@interface I (Extension) @end",
namedDecl(hasName("Extension")).bind("id"),
"@interface <<error-type>>(Extension)\n@end", /*AllowError=*/true));
}

TEST(DeclPrinter, TestObjCCategoryImplInvalidInterface) {
ASSERT_TRUE(PrintedDeclObjCMatches(
"@implementation I (Extension) @end",
namedDecl(hasName("Extension")).bind("id"),
"@implementation <<error-type>>(Extension)\n@end", /*AllowError=*/true));
}
1 change: 1 addition & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.string.strcat
libc.src.string.strlen
libc.src.string.memchr
libc.src.string.strchr
)

set(TARGET_LIBM_ENTRYPOINTS
Expand Down
1 change: 1 addition & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.string.strlen
libc.src.string.strcmp
libc.src.string.memchr
libc.src.string.strchr

# sys/mman.h entrypoints
libc.src.sys.mman.mmap
Expand Down
9 changes: 9 additions & 0 deletions libc/src/string/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ add_entrypoint_object(
memchr.h
)

add_entrypoint_object(
strchr
SRCS
strchr.cpp
HDRS
strchr.h
DEPENDS
.strlen
)

# Helper to define a function with multiple implementations
# - Computes flags to satisfy required/rejected features and arch,
Expand Down
3 changes: 2 additions & 1 deletion libc/src/string/memchr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ namespace __llvm_libc {
// TODO: Look at performance benefits of comparing words.
void *LLVM_LIBC_ENTRYPOINT(memchr)(const void *src, int c, size_t n) {
const unsigned char *str = reinterpret_cast<const unsigned char *>(src);
for (; n && *str != c; --n, ++str)
const unsigned char ch = c;
for (; n && *str != ch; --n, ++str)
;
return n ? const_cast<unsigned char *>(str) : nullptr;
}
Expand Down
26 changes: 26 additions & 0 deletions libc/src/string/strchr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===-- Implementation of strchr ------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/string/strchr.h"
#include "src/string/strlen.h"

#include "src/__support/common.h"

namespace __llvm_libc {

// TODO: Look at performance benefits of comparing words.
char *LLVM_LIBC_ENTRYPOINT(strchr)(const char *src, int c) {
unsigned char *str =
const_cast<unsigned char *>(reinterpret_cast<const unsigned char *>(src));
const unsigned char ch = c;
for (; *str && *str != ch; ++str)
;
return *str == ch ? reinterpret_cast<char *>(str) : nullptr;
}

} // namespace __llvm_libc
18 changes: 18 additions & 0 deletions libc/src/string/strchr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===-- Implementation header for strchr ------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_STRING_STRCHR_H
#define LLVM_LIBC_SRC_STRING_STRCHR_H

namespace __llvm_libc {

char *strchr(const char *src, int c);

} // namespace __llvm_libc

#endif // LLVM_LIBC_SRC_STRING_STRCHR_H
10 changes: 10 additions & 0 deletions libc/test/src/string/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ add_libc_unittest(
libc.src.string.memchr
)

add_libc_unittest(
strchr_test
SUITE
libc_string_unittests
SRCS
strchr_test.cpp
DEPENDS
libc.src.string.strchr
)

# Tests all implementations that can run on the host.
function(add_libc_multi_impl_test name)
get_property(fq_implementations GLOBAL PROPERTY ${name}_implementations)
Expand Down
9 changes: 9 additions & 0 deletions libc/test/src/string/memchr_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,12 @@ TEST(MemChrTest, SingleRepeatedCharacterShouldReturnFirst) {
// Should return original string since X is first character.
ASSERT_STREQ(call_memchr(dups, 'X', size), dups);
}

TEST(MemChrTest, SignedCharacterFound) {
char c = -1;
const size_t size = 1;
char src[size] = {c};
const char *actual = call_memchr(src, c, size);
// Should find the first character 'c'.
ASSERT_EQ(actual[0], c);
}
87 changes: 87 additions & 0 deletions libc/test/src/string/strchr_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//===-- Unittests for strchr ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/string/strchr.h"
#include "utils/UnitTest/Test.h"

TEST(StrChrTest, FindsFirstCharacter) {
const char *src = "abcde";
const char *src_copy = src;

// Should return original string since 'a' is the first character.
ASSERT_STREQ(__llvm_libc::strchr(src, 'a'), "abcde");
// Source string should not change.
ASSERT_STREQ(src, src_copy);
}

TEST(StrChrTest, FindsMiddleCharacter) {
const char *src = "abcde";
const char *src_copy = src;

// Should return characters after (and including) 'c'.
ASSERT_STREQ(__llvm_libc::strchr(src, 'c'), "cde");
// Source string should not change.
ASSERT_STREQ(src, src_copy);
}

TEST(StrChrTest, FindsLastCharacterThatIsNotNullTerminator) {
const char *src = "abcde";
const char *src_copy = src;

// Should return 'e' and null-terminator.
ASSERT_STREQ(__llvm_libc::strchr(src, 'e'), "e");
// Source string should not change.
ASSERT_STREQ(src, src_copy);
}

TEST(StrChrTest, FindsNullTerminator) {
const char *src = "abcde";
const char *src_copy = src;

// Should return null terminator.
ASSERT_STREQ(__llvm_libc::strchr(src, '\0'), "");
// Source string should not change.
ASSERT_STREQ(src, src_copy);
}

TEST(StrChrTest, CharacterNotWithinStringShouldReturnNullptr) {
// Since 'z' is not within the string, should return nullptr.
ASSERT_STREQ(__llvm_libc::strchr("123?", 'z'), nullptr);
}

TEST(StrChrTest, TheSourceShouldNotChange) {
const char *src = "abcde";
const char *src_copy = src;
// When the character is found, the source string should not change.
__llvm_libc::strchr(src, 'd');
ASSERT_STREQ(src, src_copy);
// Same case for when the character is not found.
__llvm_libc::strchr(src, 'z');
ASSERT_STREQ(src, src_copy);
// Same case for when looking for nullptr.
__llvm_libc::strchr(src, '\0');
ASSERT_STREQ(src, src_copy);
}

TEST(StrChrTest, ShouldFindFirstOfDuplicates) {
// '1' is duplicated in the string, but it should find the first copy.
ASSERT_STREQ(__llvm_libc::strchr("abc1def1ghi", '1'), "1def1ghi");

const char *dups = "XXXXX";
// Should return original string since 'X' is the first character.
ASSERT_STREQ(__llvm_libc::strchr(dups, 'X'), dups);
}

TEST(StrChrTest, EmptyStringShouldOnlyMatchNullTerminator) {
// Null terminator should match.
ASSERT_STREQ(__llvm_libc::strchr("", '\0'), "");
// All other characters should not match.
ASSERT_STREQ(__llvm_libc::strchr("", 'Z'), nullptr);
ASSERT_STREQ(__llvm_libc::strchr("", '3'), nullptr);
ASSERT_STREQ(__llvm_libc::strchr("", '*'), nullptr);
}
Loading

0 comments on commit 68adaf5

Please sign in to comment.