Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TClingDataMemberInfo.cxx
Go to the documentation of this file.
1 // @(#)root/core/meta:$Id$
2 // Author: Paul Russo 30/07/2012
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TClingDataMemberInfo
13 
14 Emulation of the CINT DataMemberInfo class.
15 
16 The CINT C++ interpreter provides an interface to metadata about
17 the data members of a class through the DataMemberInfo class. This
18 class provides the same functionality, using an interface as close
19 as possible to DataMemberInfo but the data member metadata comes
20 from the Clang C++ compiler, not CINT.
21 */
22 
23 #include "TClingDataMemberInfo.h"
24 
25 #include "TDictionary.h"
26 #include "TClingTypeInfo.h"
27 #include "TClingUtils.h"
28 #include "TClassEdit.h"
29 #include "TError.h"
30 
31 #include "clang/AST/Attr.h"
32 #include "clang/AST/ASTContext.h"
33 #include "clang/AST/Decl.h"
34 #include "clang/AST/GlobalDecl.h"
35 #include "clang/AST/Expr.h"
36 #include "clang/AST/ExprCXX.h"
37 #include "clang/AST/PrettyPrinter.h"
38 #include "clang/AST/RecordLayout.h"
39 #include "clang/AST/Type.h"
40 
41 #include "llvm/Support/Casting.h"
42 #include "llvm/Support/raw_ostream.h"
43 #include "llvm/ADT/APSInt.h"
44 #include "llvm/ADT/APFloat.h"
45 
46 using namespace clang;
47 
48 TClingDataMemberInfo::TClingDataMemberInfo(cling::Interpreter *interp,
49  TClingClassInfo *ci)
50 : TClingDeclInfo(nullptr), fInterp(interp), fClassInfo(0), fFirstTime(true), fTitle(""), fContextIdx(0U), fIoType(""), fIoName("")
51 {
52  if (!ci) {
53  // We are meant to iterate over the global namespace (well at least CINT did).
54  fClassInfo = new TClingClassInfo(interp);
55  } else {
56  fClassInfo = new TClingClassInfo(*ci);
57  }
58  if (fClassInfo->IsValid()) {
59  Decl *D = const_cast<Decl*>(fClassInfo->GetDecl());
60 
61  clang::DeclContext *dc = llvm::cast<clang::DeclContext>(D);
62  dc->collectAllContexts(fContexts);
63 
64  // Could trigger deserialization of decls.
65  cling::Interpreter::PushTransactionRAII RAII(interp);
66  fIter = llvm::cast<clang::DeclContext>(D)->decls_begin();
67  const TagDecl *TD = ROOT::TMetaUtils::GetAnnotatedRedeclarable(llvm::dyn_cast<TagDecl>(D));
68  if (TD)
69  fIter = TD->decls_begin();
70 
71  // Move to first data member.
72  InternalNext();
73  fFirstTime = true;
74  }
75 
76 }
77 
78 TClingDataMemberInfo::TClingDataMemberInfo(cling::Interpreter *interp,
79  const clang::ValueDecl *ValD,
80  TClingClassInfo *ci)
81 : TClingDeclInfo(ValD), fInterp(interp), fClassInfo(ci ? new TClingClassInfo(*ci) : new TClingClassInfo(interp, ValD)), fFirstTime(true),
82  fTitle(""), fContextIdx(0U), fIoType(""), fIoName(""){
83 
84  using namespace llvm;
85  const auto DC = ValD->getDeclContext();
86  (void)DC;
87  assert((ci || isa<TranslationUnitDecl>(DC) ||
88  ((DC->isTransparentContext() || DC->isInlineNamespace()) && isa<TranslationUnitDecl>(DC->getParent()) ) ||
89  isa<EnumConstantDecl>(ValD)) && "Not TU?");
90  assert((isa<VarDecl>(ValD) ||
91  isa<FieldDecl>(ValD) ||
92  isa<EnumConstantDecl>(ValD) ||
93  isa<IndirectFieldDecl>(ValD)) &&
94  "The decl should be either VarDecl or FieldDecl or EnumConstDecl");
95 
96 }
97 
98 void TClingDataMemberInfo::CheckForIoTypeAndName() const
99 {
100  // Three cases:
101  // 1) 00: none to be checked
102  // 2) 01: type to be checked
103  // 3) 10: none to be checked
104  // 4) 11: both to be checked
105  unsigned int code = fIoType.empty() + (int(fIoName.empty()) << 1);
106 
107  if (code == 0) return;
108 
109  const Decl* decl = GetDecl();
110 
111  if (code == 3 || code == 2) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,"ioname",fIoName);
112  if (code == 3 || code == 1) ROOT::TMetaUtils::ExtractAttrPropertyFromName(*decl,"iotype",fIoType);
113 
114 }
115 
116 TDictionary::DeclId_t TClingDataMemberInfo::GetDeclId() const
117 {
118  if (!IsValid()) {
119  return TDictionary::DeclId_t();
120  }
121  return (const clang::Decl*)(GetDecl()->getCanonicalDecl());
122 }
123 
124 int TClingDataMemberInfo::ArrayDim() const
125 {
126  if (!IsValid()) {
127  return -1;
128  }
129  // Sanity check the current data member.
130  clang::Decl::Kind DK = GetDecl()->getKind();
131  if (
132  (DK != clang::Decl::Field) &&
133  (DK != clang::Decl::Var) &&
134  (DK != clang::Decl::EnumConstant)
135  ) {
136  // Error, was not a data member, variable, or enumerator.
137  return -1;
138  }
139  if (DK == clang::Decl::EnumConstant) {
140  // We know that an enumerator value does not have array type.
141  return 0;
142  }
143  // To get this information we must count the number
144  // of array type nodes in the canonical type chain.
145  const clang::ValueDecl *VD = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
146  clang::QualType QT = VD->getType().getCanonicalType();
147  int cnt = 0;
148  while (1) {
149  if (QT->isArrayType()) {
150  ++cnt;
151  QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
152  continue;
153  }
154  else if (QT->isReferenceType()) {
155  QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
156  continue;
157  }
158  else if (QT->isPointerType()) {
159  QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
160  continue;
161  }
162  else if (QT->isMemberPointerType()) {
163  QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
164  continue;
165  }
166  break;
167  }
168  return cnt;
169 }
170 
171 int TClingDataMemberInfo::MaxIndex(int dim) const
172 {
173  if (!IsValid()) {
174  return -1;
175  }
176  // Sanity check the current data member.
177  clang::Decl::Kind DK = GetDecl()->getKind();
178  if (
179  (DK != clang::Decl::Field) &&
180  (DK != clang::Decl::Var) &&
181  (DK != clang::Decl::EnumConstant)
182  ) {
183  // Error, was not a data member, variable, or enumerator.
184  return -1;
185  }
186  if (DK == clang::Decl::EnumConstant) {
187  // We know that an enumerator value does not have array type.
188  return 0;
189  }
190  // To get this information we must count the number
191  // of array type nodes in the canonical type chain.
192  const clang::ValueDecl *VD = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
193  clang::QualType QT = VD->getType().getCanonicalType();
194  int paran = ArrayDim();
195  if ((dim < 0) || (dim >= paran)) {
196  // Passed dimension is out of bounds.
197  return -1;
198  }
199  int cnt = dim;
200  int max = 0;
201  while (1) {
202  if (QT->isArrayType()) {
203  if (cnt == 0) {
204  if (const clang::ConstantArrayType *CAT =
205  llvm::dyn_cast<clang::ConstantArrayType>(QT)
206  ) {
207  max = static_cast<int>(CAT->getSize().getZExtValue());
208  }
209  else if (llvm::dyn_cast<clang::IncompleteArrayType>(QT)) {
210  max = INT_MAX;
211  }
212  else {
213  max = -1;
214  }
215  break;
216  }
217  --cnt;
218  QT = llvm::cast<clang::ArrayType>(QT)->getElementType();
219  continue;
220  }
221  else if (QT->isReferenceType()) {
222  QT = llvm::cast<clang::ReferenceType>(QT)->getPointeeType();
223  continue;
224  }
225  else if (QT->isPointerType()) {
226  QT = llvm::cast<clang::PointerType>(QT)->getPointeeType();
227  continue;
228  }
229  else if (QT->isMemberPointerType()) {
230  QT = llvm::cast<clang::MemberPointerType>(QT)->getPointeeType();
231  continue;
232  }
233  break;
234  }
235  return max;
236 }
237 
238 int TClingDataMemberInfo::InternalNext()
239 {
240  assert(!fDecl
241  && "This is a single decl, not an iterator!");
242 
243  fNameCache.clear(); // invalidate the cache.
244  bool increment = true;
245  // Move to next acceptable data member.
246  while (fFirstTime || *fIter) {
247  // Move to next decl in context.
248  if (fFirstTime) {
249  fFirstTime = false;
250  }
251  else if (increment) {
252  ++fIter;
253  } else {
254  increment = true;
255  }
256 
257  // Handle reaching end of current decl context.
258  if (!*fIter) {
259  if (fIterStack.size()) {
260  // End of current decl context, and we have more to go.
261  fIter = fIterStack.back();
262  fIterStack.pop_back();
263  continue;
264  }
265  while (!*fIter) {
266  // Check the next decl context (of namespace)
267  ++fContextIdx;
268  if (fContextIdx >= fContexts.size()) {
269  // Iterator is now invalid.
270  return 0;
271  }
272  clang::DeclContext *dc = fContexts[fContextIdx];
273  // Could trigger deserialization of decls.
274  cling::Interpreter::PushTransactionRAII RAII(fInterp);
275  fIter = dc->decls_begin();
276  if (*fIter) {
277  // Good, a non-empty context.
278  break;
279  }
280  }
281  }
282 
283  // Valid decl, recurse into it, accept it, or reject it.
284  clang::Decl::Kind DK = fIter->getKind();
285  if (DK == clang::Decl::Enum) {
286  // We have an enum, recurse into these.
287  // Note: For C++11 we will have to check for a transparent context.
288  fIterStack.push_back(fIter);
289  cling::Interpreter::PushTransactionRAII RAII(fInterp);
290  fIter = llvm::dyn_cast<clang::DeclContext>(*fIter)->decls_begin();
291  increment = false; // avoid the next incrementation
292  continue;
293  }
294  if ((DK == clang::Decl::Field) || (DK == clang::Decl::EnumConstant) ||
295  (DK == clang::Decl::Var)) {
296  // Stop on class data members, enumerator values,
297  // and namespace variable members.
298  return 1;
299  }
300  // Collect internal `__cling_N5xxx' inline namespaces; they will be traversed later
301  if (auto NS = dyn_cast<NamespaceDecl>(*fIter)) {
302  if (NS->getDeclContext()->isTranslationUnit() && NS->isInlineNamespace())
303  fContexts.push_back(NS);
304  }
305  }
306  return 0;
307 }
308 
309 long TClingDataMemberInfo::Offset()
310 {
311  using namespace clang;
312 
313  if (!IsValid()) {
314  return -1L;
315  }
316 
317  const Decl *D = GetDecl();
318  ASTContext& C = D->getASTContext();
319  if (const FieldDecl *FldD = dyn_cast<FieldDecl>(D)) {
320  // The current member is a non-static data member.
321  const clang::RecordDecl *RD = FldD->getParent();
322  const clang::ASTRecordLayout &Layout = C.getASTRecordLayout(RD);
323  uint64_t bits = Layout.getFieldOffset(FldD->getFieldIndex());
324  int64_t offset = C.toCharUnitsFromBits(bits).getQuantity();
325  return static_cast<long>(offset);
326  }
327  else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
328  // Could trigger deserialization of decls, in particular in case
329  // of constexpr, like:
330  // static constexpr Long64_t something = std::numeric_limits<Long64_t>::max();
331  cling::Interpreter::PushTransactionRAII RAII(fInterp);
332 
333  if (long addr = reinterpret_cast<long>(fInterp->getAddressOfGlobal(GlobalDecl(VD))))
334  return addr;
335  auto evalStmt = VD->ensureEvaluatedStmt();
336  if (evalStmt && evalStmt->Value) {
337  if (const APValue* val = VD->evaluateValue()) {
338  if (VD->getType()->isIntegralType(C)) {
339  return reinterpret_cast<long>(val->getInt().getRawData());
340  } else {
341  // The VD stores the init value; its lifetime should the lifetime of
342  // this offset.
343  switch (val->getKind()) {
344  case APValue::Int: {
345  if (val->getInt().isSigned())
346  fConstInitVal.fLong = (long)val->getInt().getSExtValue();
347  else
348  fConstInitVal.fLong = (long)val->getInt().getZExtValue();
349  return (long) &fConstInitVal.fLong;
350  }
351  case APValue::Float:
352  if (&val->getFloat().getSemantics()
353  == (const llvm::fltSemantics*)&llvm::APFloat::IEEEsingle()) {
354  fConstInitVal.fFloat = val->getFloat().convertToFloat();
355  return (long)&fConstInitVal.fFloat;
356  } else if (&val->getFloat().getSemantics()
357  == (const llvm::fltSemantics*) &llvm::APFloat::IEEEdouble()) {
358  fConstInitVal.fDouble = val->getFloat().convertToDouble();
359  return (long)&fConstInitVal.fDouble;
360  }
361  // else fall-through
362  default:
363  ;// fall-through
364  };
365  // fall-through
366  } // not integral type
367  } // have an APValue
368  } // have an initializing value
369  }
370  // FIXME: We have to explicitly check for not enum constant because the
371  // implementation of getAddressOfGlobal relies on mangling the name and in
372  // clang there is misbehaviour in MangleContext::shouldMangleDeclName.
373  // enum constants are essentially numbers and don't get addresses. However
374  // ROOT expects the address to the enum constant initializer to be returned.
375  else if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D))
376  // The raw data is stored as a long long, so we need to find the 'long'
377  // part.
378 #ifdef R__BYTESWAP
379  // In this case at the beginning.
380  return reinterpret_cast<long>(ECD->getInitVal().getRawData());
381 #else
382  // In this case in the second part.
383  return reinterpret_cast<long>(((char*)ECD->getInitVal().getRawData())+sizeof(long) );
384 #endif
385  return -1L;
386 }
387 
388 long TClingDataMemberInfo::Property() const
389 {
390  if (!IsValid()) {
391  return 0L;
392  }
393  long property = 0L;
394  const clang::Decl *declaccess = GetDecl();
395  if (declaccess->getDeclContext()->isTransparentContext()) {
396  declaccess = llvm::dyn_cast<clang::Decl>(declaccess->getDeclContext());
397  if (!declaccess) declaccess = GetDecl();
398  }
399  switch (declaccess->getAccess()) {
400  case clang::AS_public:
401  property |= kIsPublic;
402  break;
403  case clang::AS_protected:
404  property |= kIsProtected;
405  break;
406  case clang::AS_private:
407  property |= kIsPrivate;
408  break;
409  case clang::AS_none:
410  if (declaccess->getDeclContext()->isNamespace()) {
411  property |= kIsPublic;
412  } else {
413  // IMPOSSIBLE
414  }
415  break;
416  default:
417  // IMPOSSIBLE
418  break;
419  }
420  if (const clang::VarDecl *vard = llvm::dyn_cast<clang::VarDecl>(GetDecl())) {
421  if (vard->isConstexpr())
422  property |= kIsConstexpr;
423  if (vard->getStorageClass() == clang::SC_Static) {
424  property |= kIsStatic;
425  } else if (declaccess->getDeclContext()->isNamespace()) {
426  // Data members of a namespace are global variable which were
427  // considered to be 'static' in the CINT (and thus ROOT) scheme.
428  property |= kIsStatic;
429  }
430  }
431  if (llvm::isa<clang::EnumConstantDecl>(GetDecl())) {
432  // Enumeration constant are considered to be 'static' data member in
433  // the CINT (and thus ROOT) scheme.
434  property |= kIsStatic;
435  }
436  const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
437  clang::QualType qt = vd->getType();
438  if (llvm::isa<clang::TypedefType>(qt)) {
439  property |= kIsTypedef;
440  }
441  qt = qt.getCanonicalType();
442  if (qt.isConstQualified()) {
443  property |= kIsConstant;
444  }
445  while (1) {
446  if (qt->isArrayType()) {
447  property |= kIsArray;
448  qt = llvm::cast<clang::ArrayType>(qt)->getElementType();
449  continue;
450  }
451  else if (qt->isReferenceType()) {
452  property |= kIsReference;
453  qt = llvm::cast<clang::ReferenceType>(qt)->getPointeeType();
454  continue;
455  }
456  else if (qt->isPointerType()) {
457  property |= kIsPointer;
458  if (qt.isConstQualified()) {
459  property |= kIsConstPointer;
460  }
461  qt = llvm::cast<clang::PointerType>(qt)->getPointeeType();
462  continue;
463  }
464  else if (qt->isMemberPointerType()) {
465  qt = llvm::cast<clang::MemberPointerType>(qt)->getPointeeType();
466  continue;
467  }
468  break;
469  }
470  if (qt->isBuiltinType()) {
471  property |= kIsFundamental;
472  }
473  if (qt.isConstQualified()) {
474  property |= kIsConstant;
475  }
476  const clang::TagType *tt = qt->getAs<clang::TagType>();
477  if (tt) {
478  const clang::TagDecl *td = tt->getDecl();
479  if (td->isClass()) {
480  property |= kIsClass;
481  }
482  else if (td->isStruct()) {
483  property |= kIsStruct;
484  }
485  else if (td->isUnion()) {
486  property |= kIsUnion;
487  }
488  else if (td->isEnum()) {
489  property |= kIsEnum;
490  }
491  }
492  // We can't be a namespace, can we?
493  // if (dc->isNamespace() && !dc->isTranslationUnit()) {
494  // property |= kIsNamespace;
495  // }
496  return property;
497 }
498 
499 long TClingDataMemberInfo::TypeProperty() const
500 {
501  if (!IsValid()) {
502  return 0L;
503  }
504  const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
505  clang::QualType qt = vd->getType();
506  return TClingTypeInfo(fInterp, qt).Property();
507 }
508 
509 int TClingDataMemberInfo::TypeSize() const
510 {
511  if (!IsValid()) {
512  return -1;
513  }
514 
515  // Sanity check the current data member.
516  clang::Decl::Kind dk = GetDecl()->getKind();
517  if ((dk != clang::Decl::Field) && (dk != clang::Decl::Var) &&
518  (dk != clang::Decl::EnumConstant)) {
519  // Error, was not a data member, variable, or enumerator.
520  return -1;
521  }
522  const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl());
523  clang::QualType qt = vd->getType();
524  if (qt->isIncompleteType()) {
525  // We cannot determine the size of forward-declared types.
526  return -1;
527  }
528  clang::ASTContext &context = GetDecl()->getASTContext();
529  // Truncate cast to fit to cint interface.
530  return static_cast<int>(context.getTypeSizeInChars(qt).getQuantity());
531 }
532 
533 const char *TClingDataMemberInfo::TypeName() const
534 {
535  if (!IsValid()) {
536  return 0;
537  }
538 
539  CheckForIoTypeAndName();
540  if (!fIoType.empty()) return fIoType.c_str();
541 
542  // Note: This must be static because we return a pointer inside it!
543  static std::string buf;
544  buf.clear();
545  if (const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl())) {
546  clang::QualType vdType = vd->getType();
547  // In CINT's version, the type name returns did *not* include any array
548  // information, ROOT's existing code depends on it.
549  while (vdType->isArrayType()) {
550  vdType = GetDecl()->getASTContext().getQualifiedType(vdType->getBaseElementTypeUnsafe(),vdType.getQualifiers());
551  }
552 
553  // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
554  vdType = ROOT::TMetaUtils::ReSubstTemplateArg(vdType, fClassInfo->GetType() );
555 
556  ROOT::TMetaUtils::GetFullyQualifiedTypeName(buf, vdType, *fInterp);
557 
558  return buf.c_str();
559  }
560  return 0;
561 }
562 
563 const char *TClingDataMemberInfo::TypeTrueName(const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt) const
564 {
565  if (!IsValid()) {
566  return 0;
567  }
568 
569  CheckForIoTypeAndName();
570  if (!fIoType.empty()) return fIoType.c_str();
571 
572  // Note: This must be static because we return a pointer inside it!
573  static std::string buf;
574  buf.clear();
575  if (const clang::ValueDecl *vd = llvm::dyn_cast<clang::ValueDecl>(GetDecl())) {
576  // if (we_need_to_do_the_subst_because_the_class_is_a_template_instance_of_double32_t)
577  clang::QualType vdType = ROOT::TMetaUtils::ReSubstTemplateArg(vd->getType(), fClassInfo->GetType());
578 
579  ROOT::TMetaUtils::GetNormalizedName(buf, vdType, *fInterp, normCtxt);
580 
581  // In CINT's version, the type name returns did *not* include any array
582  // information, ROOT's existing code depends on it.
583  // This might become part of the implementation of GetNormalizedName.
584  while (buf.length() && buf[buf.length()-1] == ']') {
585  size_t last = buf.rfind('['); // if this is not the bracket we are looking, the type is malformed.
586  if (last != std::string::npos) {
587  buf.erase(last);
588  }
589  }
590  return buf.c_str();
591  }
592  return 0;
593 }
594 
595 const char *TClingDataMemberInfo::Name()
596 {
597  if (!IsValid()) {
598  return 0;
599  }
600 
601  CheckForIoTypeAndName();
602  if (!fIoName.empty()) return fIoName.c_str();
603 
604  return TClingDeclInfo::Name();
605 }
606 
607 const char *TClingDataMemberInfo::Title()
608 {
609  if (!IsValid()) {
610  return 0;
611  }
612 
613  //NOTE: We can't use it as a cache due to the "thoughtful" self iterator
614  //if (fTitle.size())
615  // return fTitle.c_str();
616 
617  bool titleFound=false;
618  // Try to get the comment either from the annotation or the header file if present
619  std::string attribute_s;
620  const Decl* decl = GetDecl();
621  for (Decl::attr_iterator attrIt = decl->attr_begin();
622  attrIt!=decl->attr_end() && !titleFound ;++attrIt){
623  if (0 == ROOT::TMetaUtils::extractAttrString(*attrIt, attribute_s) &&
624  attribute_s.find(ROOT::TMetaUtils::propNames::separator) == std::string::npos){
625  fTitle = attribute_s;
626  titleFound=true;
627  }
628  }
629 
630  if (!titleFound && !GetDecl()->isFromASTFile()) {
631  // Try to get the comment from the header file if present
632  // but not for decls from AST file, where rootcling would have
633  // created an annotation
634  fTitle = ROOT::TMetaUtils::GetComment(*GetDecl()).str();
635  }
636 
637  return fTitle.c_str();
638 }
639 
640 // ValidArrayIndex return a static string (so use it or copy it immediately, do not
641 // call GrabIndex twice in the same expression) containing the size of the
642 // array data member.
643 llvm::StringRef TClingDataMemberInfo::ValidArrayIndex() const
644 {
645  if (!IsValid()) {
646  return llvm::StringRef();
647  }
648  const clang::DeclaratorDecl *FD = llvm::dyn_cast<clang::DeclaratorDecl>(GetDecl());
649  if (FD) return ROOT::TMetaUtils::DataMemberInfo__ValidArrayIndex(*FD);
650  else return llvm::StringRef();
651 }
652