aboutsummaryrefslogtreecommitdiff
path: root/include/lldb/Symbol/ClangExternalASTSourceCommon.h
blob: 20c4b4354367edbf7c7b6c113ecc7e99ec8f13d6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//===-- ClangExternalASTSourceCommon.h --------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_ClangExternalASTSourceCommon_h
#define liblldb_ClangExternalASTSourceCommon_h

// Clang headers like to use NDEBUG inside of them to enable/disable debug 
// related features using "#ifndef NDEBUG" preprocessor blocks to do one thing
// or another. This is bad because it means that if clang was built in release
// mode, it assumes that you are building in release mode which is not always
// the case. You can end up with functions that are defined as empty in header
// files when NDEBUG is not defined, and this can cause link errors with the
// clang .a files that you have since you might be missing functions in the .a
// file. So we have to define NDEBUG when including clang headers to avoid any
// mismatches. This is covered by rdar://problem/8691220

#if !defined(NDEBUG) && !defined(LLVM_NDEBUG_OFF)
#define LLDB_DEFINED_NDEBUG_FOR_CLANG
#define NDEBUG
// Need to include assert.h so it is as clang would expect it to be (disabled)
#include <assert.h>
#endif

#include "clang/AST/ExternalASTSource.h"

#ifdef LLDB_DEFINED_NDEBUG_FOR_CLANG
#undef NDEBUG
#undef LLDB_DEFINED_NDEBUG_FOR_CLANG
// Need to re-include assert.h so it is as _we_ would expect it to be (enabled)
#include <assert.h>
#endif

#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/Core/dwarf.h"

namespace lldb_private {

class ClangASTMetadata
{
public:
    ClangASTMetadata () :
        m_user_id(0),
        m_union_is_user_id(false),
        m_union_is_isa_ptr(false),
        m_has_object_ptr(false),
        m_is_self (false),
        m_is_dynamic_cxx (true)
    {
    }

    bool
    GetIsDynamicCXXType () const
    {
        return m_is_dynamic_cxx;
    }

    void
    SetIsDynamicCXXType (bool b)
    {
        m_is_dynamic_cxx = b;
    }

    void
    SetUserID (lldb::user_id_t user_id)
    {
        m_user_id = user_id;
        m_union_is_user_id = true;
        m_union_is_isa_ptr = false;
    }

    lldb::user_id_t
    GetUserID () const
    {
        if (m_union_is_user_id)
            return m_user_id;
        else
            return LLDB_INVALID_UID;
    }

    void
    SetISAPtr (uint64_t isa_ptr)
    {
        m_isa_ptr = isa_ptr;
        m_union_is_user_id = false;
        m_union_is_isa_ptr = true;
    }
    
    uint64_t
    GetISAPtr () const
    {
        if (m_union_is_isa_ptr)
            return m_isa_ptr;
        else
            return 0;
    }
    
    void
    SetObjectPtrName(const char *name)
    {
        m_has_object_ptr = true;
        if (strcmp (name, "self") == 0)
            m_is_self = true;
        else if (strcmp (name, "this") == 0)
            m_is_self = false;
        else
            m_has_object_ptr = false;
    }
    
    lldb::LanguageType
    GetObjectPtrLanguage () const
    {
        if (m_has_object_ptr)
        {
            if (m_is_self)
                return lldb::eLanguageTypeObjC;
            else
                return lldb::eLanguageTypeC_plus_plus;
        }
        return lldb::eLanguageTypeUnknown;
            
    }
    const char *
    GetObjectPtrName() const
    {
        if (m_has_object_ptr)
        {
            if (m_is_self)
                return "self";
            else
                return "this";
        }
        else
            return NULL;
    }
    
    bool
    HasObjectPtr() const
    {
        return m_has_object_ptr;
    }
    
    void
    Dump (Stream *s);
    
private:
    union
    {
        lldb::user_id_t m_user_id;
        uint64_t  m_isa_ptr;
    };
    bool m_union_is_user_id : 1,
         m_union_is_isa_ptr : 1,
         m_has_object_ptr : 1,
         m_is_self : 1,
         m_is_dynamic_cxx : 1;
    
};

class ClangExternalASTSourceCommon : public clang::ExternalASTSource 
{
public:
    ClangExternalASTSourceCommon();
    ~ClangExternalASTSourceCommon();

    virtual ClangASTMetadata *GetMetadata(const void *object);
    virtual void SetMetadata(const void *object, ClangASTMetadata &metadata);
    virtual bool HasMetadata(const void *object);
private:
    typedef llvm::DenseMap<const void *, ClangASTMetadata> MetadataMap;
    
    MetadataMap m_metadata;
    uint64_t    m_magic;        ///< Because we don't have RTTI, we must take it
                                ///< on faith that any valid ExternalASTSource that
                                ///< we try to use the *Metadata APIs on inherits
                                ///< from ClangExternalASTSourceCommon.  This magic
                                ///< number exists to enforce that.
};

}

#endif