Skip to content

Commit 5094e5e

Browse files
committed
NFC: Make the copies of the demangler byte-for-byte identical
With this patch, the copies of the files ItaniumDemangle.h, StringView.h, and Utility.h are kept byte-for-byte in sync between libcxxabi and llvm. All differences (namespaces, fallthrough, and unreachable macros) are defined in each copies' DemanglerConfig.h. This patch also adds a script to copy changes from libcxxabi (cp-to-llvm.sh), and a README.txt explaining the situation. Differential revision: https://reviews.llvm.org/D53538 llvm-svn: 351474
1 parent b60de17 commit 5094e5e

17 files changed

+301
-98
lines changed

libcxxabi/src/cxa_demangle.cpp

+1-6
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,8 @@
1111
// file does not yet support:
1212
// - C++ modules TS
1313

14-
#define _LIBCPP_NO_EXCEPTIONS
15-
16-
#include "__cxxabi_config.h"
17-
1814
#include "demangle/ItaniumDemangle.h"
19-
15+
#include "__cxxabi_config.h"
2016
#include <cassert>
2117
#include <cctype>
2218
#include <cstdio>
@@ -25,7 +21,6 @@
2521
#include <functional>
2622
#include <numeric>
2723
#include <utility>
28-
#include <vector>
2924

3025
using namespace itanium_demangle;
3126

libcxxabi/src/demangle/Compiler.h libcxxabi/src/demangle/DemangleConfig.h

+10-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#ifndef LIBCXX_DEMANGLE_COMPILER_H
1313
#define LIBCXX_DEMANGLE_COMPILER_H
1414

15+
#include "__config"
16+
1517
#ifdef _MSC_VER
1618
// snprintf is implemented in VS 2015
1719
#if _MSC_VER < 1900
@@ -25,10 +27,16 @@
2527

2628
#ifndef NDEBUG
2729
#if __has_attribute(noinline) && __has_attribute(used)
28-
#define DUMP_METHOD __attribute__((noinline, used))
30+
#define DEMANGLE_DUMP_METHOD __attribute__((noinline, used))
2931
#else
30-
#define DUMP_METHOD
32+
#define DEMANGLE_DUMP_METHOD
3133
#endif
3234
#endif
3335

36+
#define DEMANGLE_FALLTHROUGH _LIBCPP_FALLTHROUGH()
37+
#define DEMANGLE_UNREACHABLE _LIBCPP_UNREACHABLE()
38+
39+
#define DEMANGLE_NAMESPACE_BEGIN namespace { namespace itanium_demangle {
40+
#define DEMANGLE_NAMESPACE_END } }
41+
3442
#endif

libcxxabi/src/demangle/ItaniumDemangle.h

+14-16
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,21 @@
77
//
88
//===----------------------------------------------------------------------===//
99
//
10-
// WARNING: This file defines its contents within an anonymous namespace. It
11-
// should not be included anywhere other than cxa_demangle.h.
10+
// Generic itanium demangler library. This file has two byte-per-byte identical
11+
// copies in the source tree, one in libcxxabi, and the other in llvm.
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15-
#ifndef LIBCXX_DEMANGLE_ITANIUMDEMANGLE_H
16-
#define LIBCXX_DEMANGLE_ITANIUMDEMANGLE_H
15+
#ifndef DEMANGLE_ITANIUMDEMANGLE_H
16+
#define DEMANGLE_ITANIUMDEMANGLE_H
1717

1818
// FIXME: (possibly) incomplete list of features that clang mangles that this
1919
// file does not yet support:
2020
// - C++ modules TS
2121

22-
#include "Compiler.h"
22+
#include "DemangleConfig.h"
2323
#include "StringView.h"
2424
#include "Utility.h"
25-
2625
#include <cassert>
2726
#include <cctype>
2827
#include <cstdio>
@@ -100,8 +99,8 @@
10099
X(BracedExpr) \
101100
X(BracedRangeExpr)
102101

103-
namespace {
104-
namespace itanium_demangle {
102+
DEMANGLE_NAMESPACE_BEGIN
103+
105104
// Base class of all AST nodes. The AST is built by the parser, then is
106105
// traversed by the printLeft/Right functions to produce a demangled string.
107106
class Node {
@@ -199,7 +198,7 @@ class Node {
199198
virtual ~Node() = default;
200199

201200
#ifndef NDEBUG
202-
DUMP_METHOD void dump() const;
201+
DEMANGLE_DUMP_METHOD void dump() const;
203202
#endif
204203
};
205204

@@ -1283,7 +1282,7 @@ class ExpandedSpecialSubstitution final : public Node {
12831282
case SpecialSubKind::iostream:
12841283
return StringView("basic_iostream");
12851284
}
1286-
_LIBCPP_UNREACHABLE();
1285+
DEMANGLE_UNREACHABLE;
12871286
}
12881287

12891288
void printLeft(OutputStream &S) const override {
@@ -1335,7 +1334,7 @@ class SpecialSubstitution final : public Node {
13351334
case SpecialSubKind::iostream:
13361335
return StringView("iostream");
13371336
}
1338-
_LIBCPP_UNREACHABLE();
1337+
DEMANGLE_UNREACHABLE;
13391338
}
13401339

13411340
void printLeft(OutputStream &S) const override {
@@ -3472,7 +3471,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
34723471
Result = getDerived().parseFunctionType();
34733472
break;
34743473
}
3475-
_LIBCPP_FALLTHROUGH();
3474+
DEMANGLE_FALLTHROUGH;
34763475
}
34773476
case 'U': {
34783477
Result = getDerived().parseQualifiedType();
@@ -3759,7 +3758,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
37593758
// substitution table.
37603759
return Sub;
37613760
}
3762-
_LIBCPP_FALLTHROUGH();
3761+
DEMANGLE_FALLTHROUGH;
37633762
}
37643763
// ::= <class-enum-type>
37653764
default: {
@@ -5183,7 +5182,6 @@ struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {
51835182
Alloc>::AbstractManglingParser;
51845183
};
51855184

5186-
} // namespace itanium_demangle
5187-
} // namespace
5185+
DEMANGLE_NAMESPACE_END
51885186

5189-
#endif // LIBCXX_DEMANGLE_ITANIUMDEMANGLE_H
5187+
#endif // DEMANGLE_ITANIUMDEMANGLE_H

libcxxabi/src/demangle/README.txt

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
Itanium Name Demangler Library
2+
==============================
3+
4+
Introduction
5+
------------
6+
7+
This directory contains the generic itanium name demangler library. The main
8+
purpose of the library is to demangle C++ symbols, i.e. convert the string
9+
"_Z1fv" into "f()". You can also use the CRTP base ManglingParser to perform
10+
some simple analysis on the mangled name, or (in LLVM) use the opaque
11+
ItaniumPartialDemangler to query the demangled AST.
12+
13+
Why are there multiple copies of the this library in the source tree?
14+
---------------------------------------------------------------------
15+
16+
This directory is mirrored between libcxxabi/demangle and
17+
llvm/include/llvm/Demangle. The simple reason for this is that both projects
18+
need to demangle symbols, but neither can depend on each other. libcxxabi needs
19+
the demangler to implement __cxa_demangle, which is part of the itanium ABI
20+
spec. LLVM needs a copy for a bunch of places, but doesn't want to use the
21+
system's __cxa_demangle because it a) might not be available (i.e., on Windows),
22+
and b) probably isn't that up-to-date on the latest language features.
23+
24+
The copy of the demangler in LLVM has some extra stuff that aren't needed in
25+
libcxxabi (ie, the MSVC demangler, ItaniumPartialDemangler), which depend on the
26+
shared generic components. Despite these differences, we want to keep the "core"
27+
generic demangling library identical between both copies to simplify development
28+
and testing.
29+
30+
If you're working on the generic library, then do the work first in libcxxabi,
31+
then run the cp-to-llvm.sh script in src/demangle. This script takes as an
32+
argument the path to llvm, and re-copies the changes you made to libcxxabi over.
33+
Note that this script just blindly overwrites all changes to the generic library
34+
in llvm, so be careful.
35+
36+
Because the core demangler needs to work in libcxxabi, everything needs to be
37+
declared in an anonymous namespace (see DEMANGLE_NAMESPACE_BEGIN), and you can't
38+
introduce any code that depends on the libcxx dylib.
39+
40+
Hopefully, when LLVM becomes a monorepo, we can de-duplicate this code, and have
41+
both LLVM and libcxxabi depend on a shared demangler library.
42+
43+
Testing
44+
-------
45+
46+
The tests are split up between libcxxabi/test/{unit,}test_demangle.cpp, and
47+
llvm/unittest/Demangle. The llvm directory should only get tests for stuff not
48+
included in the core library. In the future though, we should probably move all
49+
the tests to LLVM.
50+
51+
It is also a really good idea to run libFuzzer after non-trivial changes, see
52+
libcxxabi/fuzz/cxa_demangle_fuzzer.cpp and https://llvm.org/docs/LibFuzzer.html.

libcxxabi/src/demangle/StringView.h

+35-6
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,29 @@
55
// This file is distributed under the University of Illinois Open Source
66
// License. See LICENSE.TXT for details.
77
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// FIXME: Use std::string_view instead when we support C++17.
811
//
9-
// This file is copied from llvm/lib/Demangle/StringView.h.
1012
//===----------------------------------------------------------------------===//
1113

12-
#ifndef LIBCXX_DEMANGLE_STRINGVIEW_H
13-
#define LIBCXX_DEMANGLE_STRINGVIEW_H
14+
#ifndef DEMANGLE_STRINGVIEW_H
15+
#define DEMANGLE_STRINGVIEW_H
1416

17+
#include "DemangleConfig.h"
1518
#include <algorithm>
1619
#include <cassert>
1720
#include <cstring>
1821

19-
namespace {
22+
DEMANGLE_NAMESPACE_BEGIN
23+
2024
class StringView {
2125
const char *First;
2226
const char *Last;
2327

2428
public:
29+
static const size_t npos = ~size_t(0);
30+
2531
template <size_t N>
2632
StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {}
2733
StringView(const char *First_, const char *Last_)
@@ -35,6 +41,17 @@ class StringView {
3541
return StringView(begin() + From, size() - From);
3642
}
3743

44+
size_t find(char C, size_t From = 0) const {
45+
size_t FindBegin = std::min(From, size());
46+
// Avoid calling memchr with nullptr.
47+
if (FindBegin < size()) {
48+
// Just forward to memchr, which is faster than a hand-rolled loop.
49+
if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin))
50+
return size_t(static_cast<const char *>(P) - First);
51+
}
52+
return npos;
53+
}
54+
3855
StringView substr(size_t From, size_t To) const {
3956
if (To >= size())
4057
To = size() - 1;
@@ -45,15 +62,26 @@ class StringView {
4562

4663
StringView dropFront(size_t N = 1) const {
4764
if (N >= size())
48-
N = size() - 1;
65+
N = size();
4966
return StringView(First + N, Last);
5067
}
5168

69+
StringView dropBack(size_t N = 1) const {
70+
if (N >= size())
71+
N = size();
72+
return StringView(First, Last - N);
73+
}
74+
5275
char front() const {
5376
assert(!empty());
5477
return *begin();
5578
}
5679

80+
char back() const {
81+
assert(!empty());
82+
return *(end() - 1);
83+
}
84+
5785
char popFront() {
5886
assert(!empty());
5987
return *First++;
@@ -93,6 +121,7 @@ inline bool operator==(const StringView &LHS, const StringView &RHS) {
93121
return LHS.size() == RHS.size() &&
94122
std::equal(LHS.begin(), LHS.end(), RHS.begin());
95123
}
96-
} // namespace
124+
125+
DEMANGLE_NAMESPACE_END
97126

98127
#endif

libcxxabi/src/demangle/Utility.h

+8-6
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,24 @@
55
// This file is distributed under the University of Illinois Open Source
66
// License. See LICENSE.TXT for details.
77
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// Provide some utility classes for use in the demangler(s).
811
//
9-
// This file is copied from llvm/lib/Demangle/Utility.h.
1012
//===----------------------------------------------------------------------===//
1113

12-
#ifndef LIBCXX_DEMANGLE_UTILITY_H
13-
#define LIBCXX_DEMANGLE_UTILITY_H
14+
#ifndef DEMANGLE_UTILITY_H
15+
#define DEMANGLE_UTILITY_H
1416

1517
#include "StringView.h"
16-
1718
#include <cstdint>
1819
#include <cstdlib>
1920
#include <cstring>
2021
#include <iterator>
2122
#include <limits>
2223

23-
namespace {
24+
DEMANGLE_NAMESPACE_BEGIN
25+
2426
// Stream that AST nodes write their string representation into after the AST
2527
// has been parsed.
2628
class OutputStream {
@@ -185,6 +187,6 @@ inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,
185187
return true;
186188
}
187189

188-
} // namespace
190+
DEMANGLE_NAMESPACE_END
189191

190192
#endif

libcxxabi/src/demangle/cp-to-llvm.sh

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/bin/bash
2+
3+
# Copies the 'demangle' library, excluding 'DemangleConfig.h', to llvm. If no
4+
# llvm directory is specified, then assume a monorepo layout.
5+
6+
set -e
7+
8+
FILES="ItaniumDemangle.h StringView.h Utility.h README.txt"
9+
LLVM_DEMANGLE_DIR=$1
10+
11+
if [[ -z "$LLVM_DEMANGLE_DIR" ]]; then
12+
LLVM_DEMANGLE_DIR="../../../llvm/include/llvm/Demangle"
13+
fi
14+
15+
if [[ ! -d "$LLVM_DEMANGLE_DIR" ]]; then
16+
echo "No such directory: $LLVM_DEMANGLE_DIR" >&2
17+
exit 1
18+
fi
19+
20+
read -p "This will overwrite the copies of $FILES in $LLVM_DEMANGLE_DIR; are you sure? [y/N]" -n 1 -r ANSWER
21+
echo
22+
23+
if [[ $ANSWER =~ ^[Yy]$ ]]; then
24+
for I in $FILES ; do
25+
cp $I $LLVM_DEMANGLE_DIR/$I
26+
done
27+
fi

0 commit comments

Comments
 (0)