xref: /freebsd/contrib/llvm-project/clang/lib/AST/FormatStringParsing.h (revision 5b27928474e6a4103d65b347544705c40c9618fd)
1*a7dea167SDimitry Andric //===----- FormatStringParsing.h - Format String Parsing --------*- C++ -*-===//
2*a7dea167SDimitry Andric //
3*a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*a7dea167SDimitry Andric //
7*a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
8*a7dea167SDimitry Andric //
9*a7dea167SDimitry Andric // This provides some shared functions between printf and scanf format string
10*a7dea167SDimitry Andric // parsing code.
11*a7dea167SDimitry Andric //
12*a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
13*a7dea167SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H
150b57cec5SDimitry Andric #define LLVM_CLANG_LIB_ANALYSIS_FORMATSTRINGPARSING_H
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
180b57cec5SDimitry Andric #include "clang/AST/Type.h"
190b57cec5SDimitry Andric #include "clang/AST/FormatString.h"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric namespace clang {
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric class LangOptions;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric template <typename T>
260b57cec5SDimitry Andric class UpdateOnReturn {
270b57cec5SDimitry Andric   T &ValueToUpdate;
280b57cec5SDimitry Andric   const T &ValueToCopy;
290b57cec5SDimitry Andric public:
UpdateOnReturn(T & valueToUpdate,const T & valueToCopy)300b57cec5SDimitry Andric   UpdateOnReturn(T &valueToUpdate, const T &valueToCopy)
310b57cec5SDimitry Andric     : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {}
320b57cec5SDimitry Andric 
~UpdateOnReturn()330b57cec5SDimitry Andric   ~UpdateOnReturn() {
340b57cec5SDimitry Andric     ValueToUpdate = ValueToCopy;
350b57cec5SDimitry Andric   }
360b57cec5SDimitry Andric };
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric namespace analyze_format_string {
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric OptionalAmount ParseAmount(const char *&Beg, const char *E);
410b57cec5SDimitry Andric OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E,
420b57cec5SDimitry Andric                                       unsigned &argIndex);
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric OptionalAmount ParsePositionAmount(FormatStringHandler &H,
450b57cec5SDimitry Andric                                    const char *Start, const char *&Beg,
460b57cec5SDimitry Andric                                    const char *E, PositionContext p);
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric bool ParseFieldWidth(FormatStringHandler &H,
490b57cec5SDimitry Andric                      FormatSpecifier &CS,
500b57cec5SDimitry Andric                      const char *Start, const char *&Beg, const char *E,
510b57cec5SDimitry Andric                      unsigned *argIndex);
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric bool ParseArgPosition(FormatStringHandler &H,
540b57cec5SDimitry Andric                       FormatSpecifier &CS, const char *Start,
550b57cec5SDimitry Andric                       const char *&Beg, const char *E);
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric bool ParseVectorModifier(FormatStringHandler &H,
580b57cec5SDimitry Andric                          FormatSpecifier &FS, const char *&Beg, const char *E,
590b57cec5SDimitry Andric                          const LangOptions &LO);
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric /// Returns true if a LengthModifier was parsed and installed in the
620b57cec5SDimitry Andric /// FormatSpecifier& argument, and false otherwise.
630b57cec5SDimitry Andric bool ParseLengthModifier(FormatSpecifier &FS, const char *&Beg, const char *E,
640b57cec5SDimitry Andric                          const LangOptions &LO, bool IsScanf = false);
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric /// Returns true if the invalid specifier in \p SpecifierBegin is a UTF-8
670b57cec5SDimitry Andric /// string; check that it won't go further than \p FmtStrEnd and write
680b57cec5SDimitry Andric /// up the total size in \p Len.
690b57cec5SDimitry Andric bool ParseUTF8InvalidSpecifier(const char *SpecifierBegin,
700b57cec5SDimitry Andric                                const char *FmtStrEnd, unsigned &Len);
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric template <typename T> class SpecifierResult {
730b57cec5SDimitry Andric   T FS;
740b57cec5SDimitry Andric   const char *Start;
750b57cec5SDimitry Andric   bool Stop;
760b57cec5SDimitry Andric public:
770b57cec5SDimitry Andric   SpecifierResult(bool stop = false)
Start(nullptr)780b57cec5SDimitry Andric   : Start(nullptr), Stop(stop) {}
SpecifierResult(const char * start,const T & fs)790b57cec5SDimitry Andric   SpecifierResult(const char *start,
800b57cec5SDimitry Andric                   const T &fs)
810b57cec5SDimitry Andric   : FS(fs), Start(start), Stop(false) {}
820b57cec5SDimitry Andric 
getStart()830b57cec5SDimitry Andric   const char *getStart() const { return Start; }
shouldStop()840b57cec5SDimitry Andric   bool shouldStop() const { return Stop; }
hasValue()850b57cec5SDimitry Andric   bool hasValue() const { return Start != nullptr; }
getValue()860b57cec5SDimitry Andric   const T &getValue() const {
870b57cec5SDimitry Andric     assert(hasValue());
880b57cec5SDimitry Andric     return FS;
890b57cec5SDimitry Andric   }
getValue()900b57cec5SDimitry Andric   const T &getValue() { return FS; }
910b57cec5SDimitry Andric };
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric } // end analyze_format_string namespace
940b57cec5SDimitry Andric } // end clang namespace
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric #endif
97